Dart4Flutter - 拾遺01 - flutter-dart環境搭建
Flutter 例項 - 從本地到Flutter通訊 - Event Channels
Flutter是google推出的用於移動應用開發的SDK。更多詳細資訊參考官網。
Flutter應用任然需要和本地的程式碼java或者Swift通訊。你任然需要原生程式碼獲取移動裝置硬體或者進行計算密集型操作。這個和React-Native的設計是一樣的,但是他們實現有很大的差別。
我們不討論兩個SDK誰比較厲害。我們只是研究一下,關於從原生程式碼到Flutter通訊的問題。
Flutter的官方的文件寫的非常好。在platform channels
章節,使用大量的例子詳細說明了,通過MethodChannel
和本地通訊。
但是文件只是描述從Flutter到本地的通訊,但是沒有從本地到Flutter的通訊。
需要原生程式碼的場景
實現和使用MethodChannel
介面和RPC很像。從Flutter呼叫一個本地的方法,本地方法執行,最終以一個錯誤或者資訊為響應。這種方法呼叫可以獲取當前電池的狀態、網路狀態資訊或者溫度資料。一旦本地方法做出相應,就不會再傳送任何的資訊,直到下次方法呼叫。
我對從本地到Flutter傳送資料比較感興趣。這可能包括持續更新BLE或WiFi掃描結果,加速度計和陀螺儀,甚至是密集資料收集的定期狀態更新。
在搜尋完java Api文件之後,發現了EventChannel.StreamHandler
可以解決上面的問題。Dart語言也是支援Stream
,他來自Akka/Monix/Rx,而且比較受歡迎的特性。
本地傳送資訊
新增一個針對資料流的platform channel
很簡單。你需要簡單的實現StreamHandler
介面,然後發射你的事件。
public class MainActivity extends FlutterActivity {
public static final String STREAM = "com.yourcompany.eventchannelsample/stream";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new EventChannel(getFlutterView(), STREAM).setStreamHandler(
new EventChannel.StreamHandler() {
@Override
public void onListen(Object args, final EventChannel.EventSink events) {
Log.w(TAG, "adding listener");
}
@Override
public void onCancel(Object args) {
Log.w(TAG, "cancelling listener");
}
}
);
}
}
複製程式碼
為了保證例子大多數手機可以執行,我們選用RxJava庫,將時間間隔作為事件傳送出來。注意你可以將任何的資訊傳送到Flutter應用。
public void onListen(Object args, EventChannel.EventSink events) {
Log.w(TAG, "adding listener");
timerSubscription = Observable
.interval(0, 1, TimeUnit.SECONDS)
.subscribe(
(Long timer) -> {
Log.w(TAG, "emitting timer event " + timer);
events.success(timer);// 傳送事件
},
(Throwable error) -> {
Log.e(TAG, "error in emitting timer", error);
events.error("STREAM", "Error in processing observable", error.getMessage());
},
() -> Log.w(TAG, "closing the timer observable")
);
}
@Override
public void onCancel(Object args) {
Log.w(TAG, "cancelling listener");
if (timerSubscription != null) {
timerSubscription.dispose();
timerSubscription = null;
}
}
複製程式碼
Dart 接受資訊
Dart內建支援Stream,EventChannel使用Stream的功能通知何時原生程式碼開始傳送事件和停止傳送事件。為了從本地開始傳送事件,只需要給platform channel
流新增監聽器。
static const stream =
const EventChannel('com.yourcompany.eventchannelsample/stream');
StreamSubscription _timerSubscription = null;
void _enableTimer() {
if (_timerSubscription == null) {
_timerSubscription = stream.receiveBroadcastStream().listen(_updateTimer); // 新增監聽
}
}
void _disableTimer() {
if (_timerSubscription != null) {
_timerSubscription.cancel();
_timerSubscription = null;
}
}
複製程式碼
為了顯示從本地來的更新次數,_updateTimer()
方法這是修改_timer
狀態
void _updateTimer(timer) {
debugPrint("Timer $timer");
setState(() => _timer = timer);
}
複製程式碼
下面的log展示了,新增監聽,事件傳送,事件接受,以及取消channel。
W/eventchannelsample(32641): adding listener
W/eventchannelsample(32641): emitting timer event 0
I/flutter (32641): Timer 0
W/eventchannelsample(32641): emitting timer event 1
I/flutter (32641): Timer 1
W/eventchannelsample(32641): emitting timer event 2
I/flutter (32641): Timer 2
W/eventchannelsample(32641): emitting timer event 3
I/flutter (32641): Timer 3
W/eventchannelsample(32641): emitting timer event 4
I/flutter (32641): Timer 4
W/eventchannelsample(32641): emitting timer event 5
I/flutter (32641): Timer 5
W/eventchannelsample(32641): cancelling listener
W/eventchannelsample(32641): adding listener
W/eventchannelsample(32641): emitting timer event 0
I/flutter (32641): Timer 0
W/eventchannelsample(32641): emitting timer event 1
I/flutter (32641): Timer 1
複製程式碼
總結
首先回顧了從Flutter到本地的通訊方式,而且官方文件也有詳細講解。在發現從本地到Flutter通訊的問題時,我們發現了EventChannel
,通過傳送和接受事件,完成成了本地到Flutter的通訊。