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,监听到数据作相应的逻辑便可学习