写点什么

一篇看懂 Android 与 Flutter 之间的通信,最新 Android 开发面试解答

用户头像
Android架构
关注
发布于: 刚刚

| Map | java.util.HashMap | NSDictionary |


关于编解码器,Android 端提供了以下四种。


  • BinaryCodec:是最简单的一种编解码器,其返回值类型与入参的类型相同,均为二进制格式(ByteBuffer)。由于BinaryCodec在编解码过程中什么都没做,只是原封不动的将二进制数据返回。所以传递的数据在编解码时会免于拷贝,这种方式在传递的数据量比较大时很有用。比如从 Android 侧传入一张图片到 Flutter 侧显示。

  • StandardMessageCodec:是BasicMessageChannel的默认编解码器,支持基础数据类型、列表及字典等。在编码时会先将数据写入到ByteArrayOutputStream流中,然后再将该流中的数据写入到ByteBuffer中。在解码时,直接从ByteBuffer中读取数据。

  • StandardMethodCodec:是基于StandardMessageCodec的封装。是MethodChannelEventChannel的默认编解码器。

  • StringCodec:是用于字符串与二进制数据之间的编解码,其编码格式为 UTF-8。在编码时会将 String 转成 byte 数组,然后再将该数组写入到ByteBuffer中。在解码时,直接从ByteBuffer中读取数据

  • JSONMessageCodec:内部调用StringCodec来实现编解码。

  • JSONMethodCodec:基于JSONMessageCodec的封装。可以在MethodChannelEventChannel中使用。


ByteBuffer是 Nio 中的一个类,顾名思义——就是一块存储字节的区域。它有两个实现类——DirectByteBufferHeapByteBufferDirectByteBuffer是直接在内存中开辟了一块区域来存储数据,而HeapByteBuffer是在 JVM 堆中开辟一块区域来存储数据,所以要想数据在DirectByteBuffer中与HeapByteBuffer互通,就需要进行一次拷贝。

3、通信方式

前面讲了 Android 与 flutter 通信的一些基础知识,下面就进入正题,来看 Android 如何与 flutter 进行通信。


Android 与 Flutter 之间的通信共有四种实现方式。


  1. 由于在初始化 flutter 页面时会传递一个字符串——route,因此我们就可以拿 route 来做文章,传递自己想要传递的数据。该种方式仅支持单向数据传递且数据类型只能为字符串,无返回值。

  2. 通过EventChannel来实现,EventChannel仅支持数据单向传递,无返回值。

  3. 通过MethodChannel来实现,MethodChannel支持数据双向传递,有返回值。

  4. 通过BasicMessageChannel来实现,BasicMessageChannel支持数据双向传递,有返回值。


下面就来看一下这几种方式的使用。

3.1、初始化时传值

主要是利用了创建 flutter 页面传递的 route 来做文章,笔者认为该种方式属于取巧,但还是可以用来传递数据。它的使用很简单,代码如下。


首先来看 Android 代码。


//第三个参数可以换成我们想要字符串。FlutterView flutterView = Flutter.createView(this, getLifecycle(), "route");


在 flutter 中,我们只需要通过下面代码来获取值即可。


void main() => runApp(MyApp(initParams: window.defaultRouteName,));


class MyApp extends StatelessWidget {final String initParams;//既是前面传递的值——route


MyApp({Key key, @required this.initParams}) : super(key: key);


@overrideWidget build(BuildContext context) {...}}


通过该种方式就可以在初始化 flutter 时,Android 给 flutter 传递数据。由于runApp仅会调用一次,所以该种方式只能传递一次数据且数据只能是字符串。


使用window的相关 API 需要导入包dart:ui

3.2、EventChannel

EventChannel是一种 native 向 flutter 发送数据的单向通信方式,flutter 无法返回任何数据给 native。主要用于 native 向 flutter 发送手机电量变化、网络连接变化、陀螺仪、传感器等。它的使用方式如下。


首先来看 Android 代码。


public class EventChannelPlugin implements EventChannel.StreamHandler {


private static final String TAG = EventChannelPlugin.class.getSimpleName();private EventChannel.EventSink eventSink;private Activity activity;


static EventChannelPlugin registerWith(FlutterView flutterView) {EventChannelPlugin plugin = new EventChannelPlugin(flutterView);new EventChannel(flutterView, "EventChannelPlugin").setStreamHandler(plugin);return plugin;


}


private EventChannelPlugin(FlutterView flutterView) {this.activity = (Activity) flutterView.getContext();}


void send(Object params) {if (eventSink != null) {eventSink.success(params);}}


void sendError(String str1, String str2, Object params) {if (eventSink != null) {eventSink.error(str1, str2, params);}}


void cancel() {if (eventSink != null) {eventSink.endOfStream();}}//第一个参数为 flutter 初始化 EventChannel 时返回的值,仅此一次 @Overridepublic void onListen(Object o, EventChannel.EventSink eventSink) {this.eventSink = eventSink;Log.i(TAG, "eventSink:" + eventSink);Log.i(TAG, "Object:" + o.toString());Toast.makeText(activity, "onListen——obj:" + o, Toast.LENGTH_SHORT).show();}


@Overridepublic void onCancel(Object o) {Log.i(TAG, "onCancel:" + o.toString());Toast.makeText(activity, "onCancel——obj:" + o, Toast.LENGTH_SHORT).show();this.eventSink = null;}}


笔者对 Android 端代码做了一个简单的封装,还是很好理解的。下面就来看 flutter 代码实现。


class _MyHomePageState extends State<MyHomePage> {EventChannel _eventChannelPlugin = EventChannel("EventChannelPlugin");StreamSubscription _streamSubscription;@overridevoid initState() {_streamSubscription = _eventChannelPlugin//["abc", 123, "你好"]对应着 Android 端 onListen 方法的第一个参数,可不传值.receiveBroadcastStream(["abc", 123, "你好"]).listen(_onToDart, onError: _onToDartError, onDone: _onDone);super.initState();}


@overridevoid dispose() {if (_streamSubscription != null) {_streamSubscription.cancel();_streamSubscription = null;}super.dispose();}//native 端发送正常数据 void _onToDart(message) {print(message);}//当 native 出错时,发送的数据 void _onToDartError(error) {print(error);}//当 native 发送数据完成时调用的方法,每一次发送完成就会调用 void _onDone() {


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


print("消息传递完毕");}


@overrideWidget build(BuildContext context) {...}}


上面就是通过EventChannel来进行通信的代码实现,调用EventChannelPluginsend方法就能给 flutter 发送数据。

3.3、MethodChannel

MethodChannel是一种 native 与 flutter 之间互相发送数据的通信方式,顾名思义,通过MethodChannel就能调用 native 与 flutter 中相对应的方法,该种方式有返回值。它的使用方式如下。


首先来看 Android 端的代码实现。


public class MethodChannelPlugin implements MethodChannel.MethodCallHandler {


private Activity activity;private MethodChannel channel;


public static MethodChannelPlugin registerWith(FlutterView flutterView) {MethodChannel channel = new MethodChannel(flutterView, "MethodChannelPlugin");MethodChannelPlugin methodChannelPlugin = new MethodChannelPlugin((Activity) flutterView.getContext(), channel);channel.setMethodCallHandler(methodChannelPlugin);return methodChannelPlugin;}


private MethodChannelPlugin(Activity activity, MethodChannel channel) {this.activity = activity;this.channel = channel;


}//调用 flutter 端方法,无返回值 public void invokeMethod(String method, Object o) {channel.invokeMethod(method, o);}//调用 flutter 端方法,有返回值 public void invokeMethod(String method, Object o, MethodChannel.Result result) {channel.invokeMethod(method, o, result);}


@Overridepublic void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {switch (methodCall.method) {case "send"://返回的方法名//给 flutter 端的返回值 result.success("MethodChannelPlugin 收到:" + methodCall.arguments);Toast.makeText(activity, methodCall.arguments + "", Toast.LENGTH_SHORT).show();if (activity instanceof FlutterAppActivity) {((FlutterAppActivity) activity).showContent(methodCall.arguments);}break;default:result.notImplemented();break;}}}


笔者对 Android 端代码做了一个简单的封装,还是很好理解的。下面就来看 flutter 代码实现。


class _MyHomePageState extends State<MyHomePage> {MethodChannel _methodChannel = MethodChannel("MethodChannelPlugin");@overridevoid initState() {_methodChannel.setMethodCallHandler((handler) => Future<String>(() {print("_methodChannel:${handler}");//监听 native 发送的方法名及参数 switch (handler.method) {case "send":_send(handler.arguments);//handler.arguments 表示 native 传递的方法参数 break;}}));super.initState();}//native 调用的 flutter 方法 void _send(arg) {setState(() {_content = arg;});}String _resultContent = "";


//flutter 调用 native 的相应方法 void _sendToNative() {

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
一篇看懂Android与Flutter之间的通信,最新Android开发面试解答