Android与Flutter之间如何实现通信
Android与Flutter之间如何实现通信
这篇“Android与Flutter之间如何实现通信”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Android与Flutter之间如何实现通信”文章吧。
1、架构概述
消息通过平台通道在native(host)与flutter(client)之间传递,如下图所示:
为了确保用户界面能够正确响应,消息都是以异步的方式进行传递。无论是native向flutter发送消息,还是flutter向native发送消息。
在flutter中,MethodChannel可以发送与方法调用相对应的消息。在native平台上,MethodChannel在Android可以接收方法调用并返回结果。这些类可以帮助我们用很少的代码就能开发平台插件。
注意:本节内容来自flutter官网,读者可自行查阅。
2、平台通道数据类型支持和编解码器
平台通道可以使用提供的编解码器对消息进行编解码,这些编解码器支持简单类似JSON的值的高效二进制序列化,例如布尔值,数字,字符串,字节缓冲区以及这些的列表和映射。当你发送和接收值时,会自动对这些值进行序列化和反序列化。
下表显示了如何在平台端接收Dart值,反之亦然:
关于编解码器,Android端提供了以下几种。
BinaryCodec:是最简单的一种编解码器,其返回值类型与入参的类型相同,均为二进制格式(ByteBuffer)。由于BinaryCodec在编解码过程中什么都没做,只是原封不动的将二进制数据返回。所以传递的数据在编解码时会免于拷贝,这种方式在传递的数据量比较大时很有用。比如从Android侧传入一张图片到Flutter侧显示。
StandardMessageCodec:是BasicMessageChannel的默认编解码器,支持基础数据类型、列表及字典等。在编码时会先将数据写入到ByteArrayOutputStream流中,然后再将该流中的数据写入到ByteBuffer中。在解码时,直接从ByteBuffer中读取数据。
StandardMethodCodec:是基于StandardMessageCodec的封装。是MethodChannel与EventChannel的默认编解码器。
StringCodec:是用于字符串与二进制数据之间的编解码,其编码格式为UTF-8。在编码时会将String转成byte数组,然后再将该数组写入到ByteBuffer中。在解码时,直接从ByteBuffer中读取数据
JSONMessageCodec:内部调用StringCodec来实现编解码。
JSONMethodCodec:基于JSONMessageCodec的封装。可以在MethodChannel与EventChannel中使用。
ByteBuffer是Nio中的一个类,顾名思义——就是一块存储字节的区域。它有两个实现类——DirectByteBuffer与HeapByteBuffer,DirectByteBuffer是直接在内存中开辟了一块区域来存储数据,而HeapByteBuffer是在JVM堆中开辟一块区域来存储数据,所以要想数据在DirectByteBuffer中与HeapByteBuffer互通,就需要进行一次拷贝。
3、通信方式
前面讲了Android与flutter通信的一些基础知识,下面就进入正题,来看Android如何与flutter进行通信。
Android与Flutter之间的通信共有四种实现方式。
由于在初始化flutter页面时会传递一个字符串——route,因此我们就可以拿route来做文章,传递自己想要传递的数据。该种方式仅支持单向数据传递且数据类型只能为字符串,无返回值。
通过EventChannel来实现,EventChannel仅支持数据单向传递,无返回值。
通过MethodChannel来实现,MethodChannel支持数据双向传递,有返回值。
通过BasicMessageChannel来实现,BasicMessageChannel支持数据双向传递,有返回值。
下面就来看一下这几种方式的使用。
3.1、初始化时传值
主要是利用了创建flutter页面传递的route来做文章,笔者认为该种方式属于取巧,但还是可以用来传递数据。它的使用很简单,代码如下。
首先来看Android代码。
//第三个参数可以换成我们想要字符串。FlutterViewflutterView=Flutter.createView(this,getLifecycle(),"route");
在flutter中,我们只需要通过下面代码来获取值即可。
voidmain()=>runApp(MyApp(initParams:window.defaultRouteName,));classMyAppextendsStatelessWidget{finalStringinitParams;//既是前面传递的值——routeMyApp({Keykey,@requiredthis.initParams}):super(key:key);@overrideWidgetbuild(BuildContextcontext){...}}
通过该种方式就可以在初始化flutter时,Android给flutter传递数据。由于runApp仅会调用一次,所以该种方式只能传递一次数据且数据只能是字符串。
使用window的相关API需要导入包dart:ui
3.2、EventChannel
EventChannel是一种native向flutter发送数据的单向通信方式,flutter无法返回任何数据给native。主要用于native向flutter发送手机电量变化、网络连接变化、陀螺仪、传感器等。它的使用方式如下。
首先来看Android代码。
publicclassEventChannelPluginimplementsEventChannel.StreamHandler{privatestaticfinalStringTAG=EventChannelPlugin.class.getSimpleName();privateEventChannel.EventSinkeventSink;privateActivityactivity;staticEventChannelPluginregisterWith(FlutterViewflutterView){EventChannelPluginplugin=newEventChannelPlugin(flutterView);newEventChannel(flutterView,"EventChannelPlugin").setStreamHandler(plugin);returnplugin;}privateEventChannelPlugin(FlutterViewflutterView){this.activity=(Activity)flutterView.getContext();}voidsend(Objectparams){if(eventSink!=null){eventSink.success(params);}}voidsendError(Stringstr1,Stringstr2,Objectparams){if(eventSink!=null){eventSink.error(str1,str2,params);}}voidcancel(){if(eventSink!=null){eventSink.endOfStream();}}//第一个参数为flutter初始化EventChannel时返回的值,仅此一次@OverridepublicvoidonListen(Objecto,EventChannel.EventSinkeventSink){this.eventSink=eventSink;Log.i(TAG,"eventSink:"+eventSink);Log.i(TAG,"Object:"+o.toString());Toast.makeText(activity,"onListen——obj:"+o,Toast.LENGTH_SHORT).show();}@OverridepublicvoidonCancel(Objecto){Log.i(TAG,"onCancel:"+o.toString());Toast.makeText(activity,"onCancel——obj:"+o,Toast.LENGTH_SHORT).show();this.eventSink=null;}}
笔者对Android端代码做了一个简单的封装,还是很好理解的。下面就来看flutter代码实现。
class_MyHomePageStateextendsState
上面就是通过EventChannel来进行通信的代码实现,调用EventChannelPlugin的send方法就能给flutter发送数据。
3.3、MethodChannel
MethodChannel是一种native与flutter之间互相发送数据的通信方式,顾名思义,通过MethodChannel就能调用native与flutter中相对应的方法,该种方式有返回值。它的使用方式如下。
首先来看Android端的代码实现。
publicclassMethodChannelPluginimplementsMethodChannel.MethodCallHandler{privateActivityactivity;privateMethodChannelchannel;publicstaticMethodChannelPluginregisterWith(FlutterViewflutterView){MethodChannelchannel=newMethodChannel(flutterView,"MethodChannelPlugin");MethodChannelPluginmethodChannelPlugin=newMethodChannelPlugin((Activity)flutterView.getContext(),channel);channel.setMethodCallHandler(methodChannelPlugin);returnmethodChannelPlugin;}privateMethodChannelPlugin(Activityactivity,MethodChannelchannel){this.activity=activity;this.channel=channel;}//调用flutter端方法,无返回值publicvoidinvokeMethod(Stringmethod,Objecto){channel.invokeMethod(method,o);}//调用flutter端方法,有返回值publicvoidinvokeMethod(Stringmethod,Objecto,MethodChannel.Resultresult){channel.invokeMethod(method,o,result);}@OverridepublicvoidonMethodCall(MethodCallmethodCall,MethodChannel.Resultresult){switch(methodCall.method){case"send"://返回的方法名//给flutter端的返回值result.success("MethodChannelPlugin收到:"+methodCall.arguments);Toast.makeText(activity,methodCall.arguments+"",Toast.LENGTH_SHORT).show();if(activityinstanceofFlutterAppActivity){((FlutterAppActivity)activity).showContent(methodCall.arguments);}break;default:result.notImplemented();break;}}}
笔者对Android端代码做了一个简单的封装,还是很好理解的。下面就来看flutter代码实现。
class_MyHomePageStateextendsState
上面就是通过MethodChannel来进行通信的代码实现。还是比较简单的。在Android端使用只需要调用MethodChannelPlugin的invokeMethod方法即可。在flutter端使用只需要参考_sendToNative方法的实现即可。
3.4、BasicMessageChannel
BasicMessageChannel是一种能够在native与flutter之间互相发送消息的通信方式,它支持数据类型最多,使用范围最广。EventChannel与MethodChannel的应用场景可以使用BasicMessageChannel来实现,但BasicMessageChannel的应用场景就不一定能够使用EventChannel与MethodChannel来实现。该方式有返回值。它的使用方式如下。
首先来看Android代码的实现。
//这里支持的数据类型为String。publicclassBasicMessageChannelPluginimplementsBasicMessageChannel.MessageHandler
笔者对Android端代码做了一个简单的封装,还是很好理解的。下面就来看flutter代码实现。
class_MyHomePageStateextendsState
上面就是通过BasicMessageChannel来进行通信的代码实现。在Android端只需要调用BasicMessageChannelPlugin的send方法就可以向flutter发送数据,BasicMessageChannel.Reply是返回值的回调方法。在flutter端使用只需要参考_sendToNative方法的实现即可。
4、通信原理
从分析Android与Flutter通信的源码来看,实现还是比较简单的,都是以ByteBuffer为数据载体,然后通过BinaryMessenger来发送与接收数据。整体设计如下。
从图中可以看出,Android侧与flutter侧采用了相同的设计。前面说过通信时是异步进行的,那么线程切换在哪?其实是在系统底层实现的。在Android与Flutter通信中,系统底层屏蔽了线程切换、数据拷贝等大量复杂操作。使得Android侧与flutter侧能方便的来进行通信。
在Android侧,BinaryMessenger是一个接口,在FlutterView中实现了该接口,在BinaryMessenger的方法中通过JNI来与系统底层沟通。在Flutter侧,BinaryMessenger是一个类,该类的作用就是与类window沟通,而类window才真正与系统底层沟通。
以上就是关于“Android与Flutter之间如何实现通信”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注恰卡编程网行业资讯频道。
推荐阅读
-
我的世界windows版怎么下载手机版
-
android(如何快速开发框架 小米note开发版MIUI,安卓6.0,怎么安装Xposed框架)
稳定版,你必须先根除。你上网搜索安卓可以叫别人s框架,对方可以把框架做成jar包,把这个jar包加载到项目目录的libs文件中使...
-
android(studio 虚拟机启动不了 android studio可以当模拟器用吗)
androidstudio可以当模拟器用吗?AmdCUP引导模拟器有点复杂。雷电模拟器上的抖音怎么登录不上?不是,闪电模拟调用...
-
从实践中学习手机抓包与数据分析(android 手机抓包app)
android手机抓包app?netcapture抓包精灵app(手机抓包工具)又名sslcapture,是什么专业的安卓手机抓...
-
android(studio全局搜索 android studio怎么看app界面)
androidstudio怎么看app界面?在设备桌面点击运用直接进入到App界面,就也可以参与其他你的操作了。android-...
-
怎么把android框架源代码拉到本地(android studio如何运行别人的源代码)
androidstudio如何运行别人的源代码?androidstudio点击刚建在列表中你选择导入module,导入即可在用...
-
android(studio2022年使用教程 怎么安装Android studio详细教程)
怎么安装Androidstudio详细教程?androidstudio中haxm直接安装的方法追加:1、简单的方法打开Andr...
-
怎么使用Android基准配置文件Baseline Profile方案提升启动速度
怎么使用Android基准配置文件Baseline Profile方案提升启动速度...
-
HTML5如何实现禁止android视频另存为
HTML5如何实现禁止android视频另存为今天小编给大家分享一...
-
学java好还是学php好?