從搭建環境到項目開發,入坑flutter已經快一週了,不得不說,從android原生開發者角度來講,相對於其餘的跨平臺方案,無論是性能,UI渲染仍是學習成本,flutter仍是相對比較友好的,內部維護幾套UI邏輯,skia引擎渲染,而不依賴於原生控件的侷限性,Hotload開發快捷等等,但咱們要明白一點,flutter始終是一個跨平臺的UI方案,最終仍是要根據平臺生成.apk(android)/.ipa(ios)包的,因此在涉及到一些系統平臺的接口或者數據,好比系統電量什麼的,仍是須要native層去搞定的,再將數據返回給flutter層去展現,因此不免就會出現flutter與native的通訊問題,那麼Flutter是如何作到的呢?答案是Platform Channelsjava
上圖來自Flutter官網,代表了Platform Channels的架構示意圖。有細心的同窗就要問了,你不是說Flutter和Native通訊是經過Platform Channels嗎?怎麼架構圖裏面鏈接他們的是MethodChannel? 其實呢,MethodChannel是Platform Channels中的一種,顧名思義,MethodChannel用起來應該和方法調用差很少。那麼還有別的channel?有的,還有EventChannel,BasicMessageChannel等。若是你須要把數據從Native平臺發送給Flutter,推薦你使用EventChannel。Flutter framework也是在用這些通道和Native通訊android
雖然flutter自己提供了2種日誌輸出方式,print(),debugprint(),可是對於android開發者來講仍是不太習慣,並且信息冗餘在console欄裏面,無法過濾等等,因此能夠經過這個Channels去調用android原生的logcatios
import 'package:flutter/services.dart';
class LogUtils {
static const perform = const MethodChannel("android_log");
static void v(String tag, String message) {
perform.invokeMethod('logV', {'tag': tag, 'msg': message});
}
static void d(String tag, String message) {
perform.invokeMethod('logD', {'tag': tag, 'msg': message});
}
static void i(String tag, String message) {
perform.invokeMethod('logI', {'tag': tag, 'msg': message});
}
static void w(String tag, String message) {
perform.invokeMethod('logW', {'tag': tag, 'msg': message});
}
static void e(String tag, String message) {
perform.invokeMethod('logE', {'tag': tag, 'msg': message});
}
}
複製代碼
能夠看到,代碼很簡單,初始化一個MethodChannel對象,而後去調用invokeMethod方法,傳入參數便可架構
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
new MethodChannel(getFlutterView(),CHANNEL).setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
String tag = methodCall.argument("tag");
String msg = methodCall.argument("msg");
switch (methodCall.method) {
case "logV":
Log.v(tag,msg);
break;
case "logD":
Log.d(tag,msg);
break;
case "logI":
Log.i(tag,msg);
break;
case "logW":
Log.w(tag,msg);
break;
case "logE":
Log.e(tag,msg);
break;
default:
Log.d(tag,msg);
break;
}
}
});
}
複製代碼
這裏也是建立一個MethodCallHandler對象,在回調中收到MethodCall對象,取出對應的method和arguments,這裏判斷method來調用android自己的log方法便可。ide
由於如今其實大部分都是flutter和native原生開發,因此有不少flutter須要主動去推送消息給native層,native層就能夠建立EventChannel來監聽與flutter的狀態,再經過EventSink對象回覆消息obj性能
new EventChannel(getFlutterView(), "com.flutter/notify").setStreamHandler(
new EventChannel.StreamHandler() {
private TokenReceiver tokenReceiver;
@Override
public void onListen(Object args, final EventChannel.EventSink events) {
Log.e("tag", "adding listener");
events.success("data callback");
}
@Override
public void onCancel(Object args) {
Log.e("tag", "cancelling listener");
}
}
);
複製代碼
static const EventChannel eventChannel = EventChannel('com.flutter/notify');
@override
void initState() {
// TODO: implement initState
super.initState();
//初始化監聽
eventChannel.receiveBroadcastStream().listen(_onDataBack, onError: _onError);
}
void _onError(Object error){
}
void _onDataBack(String callback) {
print(callback)
}
複製代碼
代碼也很簡單,建立相同Channel名字的EventChannel,監聽到數據作相應的邏輯便可學習