flutter 與native通訊初探

flutter 從入門到放棄

背景

從搭建環境到項目開發,入坑flutter已經快一週了,不得不說,從android原生開發者角度來講,相對於其餘的跨平臺方案,無論是性能,UI渲染仍是學習成本,flutter仍是相對比較友好的,內部維護幾套UI邏輯,skia引擎渲染,而不依賴於原生控件的侷限性,Hotload開發快捷等等,但咱們要明白一點,flutter始終是一個跨平臺的UI方案,最終仍是要根據平臺生成.apk(android)/.ipa(ios)包的,因此在涉及到一些系統平臺的接口或者數據,好比系統電量什麼的,仍是須要native層去搞定的,再將數據返回給flutter層去展現,因此不免就會出現flutter與native的通訊問題,那麼Flutter是如何作到的呢?答案是Platform Channelsjava

Platform Channels

1975877-6079b324ae9d7bf7

上圖來自Flutter官網,代表了Platform Channels的架構示意圖。有細心的同窗就要問了,你不是說Flutter和Native通訊是經過Platform Channels嗎?怎麼架構圖裏面鏈接他們的是MethodChannel? 其實呢,MethodChannel是Platform Channels中的一種,顧名思義,MethodChannel用起來應該和方法調用差很少。那麼還有別的channel?有的,還有EventChannel,BasicMessageChannel等。若是你須要把數據從Native平臺發送給Flutter,推薦你使用EventChannel。Flutter framework也是在用這些通道和Native通訊android

例子1:flutter調用android logcat

雖然flutter自己提供了2種日誌輸出方式,print(),debugprint(),可是對於android開發者來講仍是不太習慣,並且信息冗餘在console欄裏面,無法過濾等等,因此能夠經過這個Channels去調用android原生的logcatios

Flutter端
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方法,傳入參數便可架構

android端
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

例子2:android推送消息到flutter

由於如今其實大部分都是flutter和native原生開發,因此有不少flutter須要主動去推送消息給native層,native層就能夠建立EventChannel來監聽與flutter的狀態,再經過EventSink對象回覆消息obj性能

android端
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");
                    }
                }
        );
複製代碼
flutter
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,監聽到數據作相應的邏輯便可學習

相關文章
相關標籤/搜索