Flutter飞起前端开发那些事儿Flutter

Flutter(七)Flutter与Android通信

2020-08-17  本文已影响0人  Geekholt

因为笔者本身主要从事是Android开发,所以很多角度都是作为一个Android开发者学习Flutter的角度出发,IOS或者H5的开发同学可以选择性阅读

目录

Demo地址:https://github.com/Geekholt/FlutterHybridAndroid

前言

用Flutter这样的跨平台技术进行商业级项目开发时,几乎不可避免的需要和Native进行通信,比如不同平台的底层服务如电量变化、网络连接变化、陀螺仪、传感器等等都有各自不同的实现,以及编译期的一些配置,比如包名、版本号、第三方依赖APPKEY等都需要通过原生的方法去获取。所以学习Native和Flutter的通信方式是非常有必要的

Native和Flutter之间可以通过Platform Channels APIs进行通信,Flutter定义了三种不同类型的Channel

MethodChannel通信

MethodChannel是最常用的Native和Flutter的通信方式,主要用于Flutter调用Native端方法,如调用Native相机功能

为了便于理解,这里我介绍一个前两天在公司项目中实际用到MethodChannel的场景。基本现在Android APP都会涉及到多渠道打包问题,针对不同的渠道,我们可能会在编译脚本(build文件)中进行一些不同的配置。但是Flutter如何才能拿到Android Gradle中的配置信息呢?其实很简单,也就是我们可以先通过Android代码拿到BuildConfig中的数据,再通过Flutter与Android进行通信拿到数据。这种一次性的调用Android中代码的情况就需要用到MethodChannel

Android端

创建MethodChannel,通过setMethodCallHandler接收Flutter端的方法调用

//1.创建android端的MethodChannel
MethodChannel channel = new MethodChannel(messenger, "com.geekholt.hybird/TestMethodChannel");
//2.通过setMethodCallHandler响应Flutter端的方法调用
channel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
    @Override
    public void onMethodCall(MethodCall call, MethodChannel.Result result) {
        switch (call.method) {
            case "getUmAppKey":
                    //3.返回结果给Flutter端
                result.success(BuildConfig.UMENG_APP_KEY);
                break;
            default:
                result.notImplemented();
        }
    }
});

注:messenger需要在FlutterActivity中使用getFlutterEngine().getDartExecutor()获取

Flutter端

Flutter端同样也有MethodChannel,可以通过类似方法调用的方式,调用Native层的方法,并拿到返回值

//1.创建Flutter端的MethodChannel
MethodChannel _methodChannel = MethodChannel('com.geekholt.hybird/TestMethodChannel');
//2.通过invokeMethod调用Native方法,拿到返回值
void _getChannel(value) async {
  String appKey = await _methodChannel.invokeMethod('getUmAppKey', value);
  print("appKey:" + appKey);
}

这里要注意两点:

  1. ChannelName要与Native端保持一致(即com.geekholt.hybird/TestMethodChannel
  2. MethodName要与Native端保持一致(即getUmAppKey

BasicMessageChannel通信

BasicMessageChannel用于Native和Flutter互相发送消息,一方给另一方发送消息,收到消息之后给出回复

Android给Flutter发送消息

Android端

创建一个BasicMessageChannel,通过send方法发送消息

//1.创建android端的BasicMessageChannel
BasicMessageChannel<String> messageChannel = new BasicMessageChannel<>(messenger, "com.geekholt.hybird/TestBasicMessageChannel", StringCodec.INSTANCE);
//2.向Flutter端发送消息
messageChannel.send(message, new BasicMessageChannel.Reply<String>() {
      @Override
      public void reply(String reply) {
         Log.i(TAG, "收到Flutter的消息回复:" + message);
      }
});

发送的消息会以二进制的形式进行处理,所以要针对不同类型的数据进行二进制编码

编码类型 消息格式
BinaryCodec 发送二进制消息时
JSONMessageCodec 发送Json格式消息时
StandardMessageCodec 发送基本型数据时
StringCodec 发送String类型消息时

Flutter端

Flutter端同样也有BasicMessageChannel,通过setMessageHandler接收并回复消息

//1.创建Flutter端的BasicMessageChannel
BasicMessageChannel<String> _basicMessageChannel = BasicMessageChannel('com.geekholt.hybird/TestBasicMessageChannel', StringCodec());

//2.接收来自Native的消息,并向Native回复
_basicMessageChannel.setMessageHandler((String message) => Future<String>(() {
      return "收到Native的消息:" + message;
}));

Flutter给Android发送消息

Flutter端

在Flutter端我们也可以通过send方法向Native发送消息,方法的返回值就是Native端的消息回复

注意flutter和Native的通信都是异步的

void _sendMessage(value) async {
  String response = await _basicMessageChannel.send(value);
  print("收到Native的消息回复:"+ response);
}

Android端

android端通过setMessageHandler设置消息处理器,处理来自Dart的消息,收到消息后通过reply进行回复

messageChannel.setMessageHandler(new BasicMessageChannel.MessageHandler<String>() {
    @Override
    public void onMessage(String message, BasicMessageChannel.Reply<String> reply) {
        //通过reply进行回复
        reply.reply("BasicMessageChannel收到:" + message);
    }
});

EventChannel通信

EventChannel用于从Native向Flutter发送通知事件,例如Flutter通过其监听Android的重力感应变化等。与MethodChannel不同,EventChannel是Native到Flutter的单向调用,调用是一对多的,类似Android的BrodcastReceiver

Android端

创建一个EventChannel,在StreamHandler#onLister回调中获取EventSink引用并保存,当重力感应发送变化时,通过eventSink.success向Flutter端发送消息

private EventChannel.EventSink eventSink;

void registerWith(BinaryMessenger messenger) {
    //1.创建Android端的EventChannel
    EventChannel eventChannel = new EventChannel(messenger, "com.geekholt.hybird/TestEventChannel");
    //2.在StreamHandler#onLister回调中获取EventSink引用并保存
    eventChannel.setStreamHandler(new EventChannel.StreamHandler() {
        @Override
        public void onListen(Object arguments, EventChannel.EventSink events) {
            eventSink = events;
        }

        @Override
        public void onCancel(Object arguments) {
            eventSink = null;
        }
    });
}

//3.调用eventSink.success向Flutter端发送消息
void send(Object params) {
    if (eventSink != null) {
        eventSink.success(params);
    }
}

Flutter端

Flutter端接收消息如下所示,要注意使用EventChannel时需要在页面销毁时取消监听,防止内存泄漏

//1.创建Flutter端EventChannel
EventChannel _eventChannelPlugin = EventChannel('com.geekholt.hybird/TestEventChannel');
//2.EventChannel#receiveBroadcastStream注册listener,建立监听
StreamSubscription _streamSubscription = _eventChannelPlugin
    .receiveBroadcastStream()
    .listen(_onEventSuccess, onError: _onEventError);

//3.成功和错误回调
void _onEventSuccess(message) {
  print(message);
}
void _onEventError(error) {
  print(error);
}

//4.注意:页面销毁时需要取消监听,防止内存泄漏
@override
void dispose() {
  if (_streamSubscription != null) {
    _streamSubscription.cancel();
    _streamSubscription = null;
  }
  super.dispose();
}
上一篇下一篇

猜你喜欢

热点阅读