android与flutter之间如何实现通信-mile米乐体育

android与flutter之间如何实现通信

这篇“android与flutter之间如何实现通信”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“android与flutter之间如何实现通信”文章吧。

1、架构概述

消息通过平台通道在native(host)与flutter(client)之间传递,如下图所示:

为了确保用户界面能够正确响应,消息都是以异步的方式进行传递。无论是native向flutter发送消息,还是flutter向native发送消息。

在flutter中,methodchannel可以发送与方法调用相对应的消息。在native平台上,methodchannel在android可以接收方法调用并返回结果。这些类可以帮助我们用很少的代码就能开发平台插件。

注意:本节内容来自flutter米乐app官网登录官网,读者可自行查阅。

2、平台通道数据类型支持和编解码器

平台通道可以使用提供的编解码器对消息进行编解码,这些编解码器支持简单类似json的值的高效二进制序列化,例如布尔值,数字,字符串,字节缓冲区以及这些的列表和映射。当你发送和接收值时,会自动对这些值进行序列化和反序列化。

下表显示了如何在平台端接收dart值,反之亦然:

关于编解码器,android端提供了以下几种。

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

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

  3. standardmethodcodec:是基于standardmessagecodec的封装。是methodchannel与eventchannel的默认编解码器。

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

  5. jsonmessagecodec:内部调用stringcodec来实现编解码。

  6. jsonmethodcodec:基于jsonmessagecodec的封装。可以在methodchannel与eventchannel中使用。

bytebuffer是nio中的一个类,顾名思义——就是一块存储字节的区域。它有两个实现类——directbytebuffer与heapbytebuffer,directbytebuffer是直接在内存中开辟了一块区域来存储数据,而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代码。

//第三个参数可以换成我们想要字符串。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=eventchannel("eventchannelplugin");streamsubscription_streamsubscription;@overridevoidinitstate(){_streamsubscription=_eventchannelplugin//["abc",123,"你好"]对应着android端onlisten方法的第一个参数,可不传值.receivebroadcaststream(["abc",123,"你好"]).listen(_ontodart,onerror:_ontodarterror,ondone:_ondone);super.initstate();}@overridevoiddispose(){if(_streamsubscription!=null){_streamsubscription.cancel();_streamsubscription=null;}super.dispose();}//native端发送正常数据void_ontodart(message){print(message);}//当native出错时,发送的数据void_ontodarterror(error){print(error);}//当native发送数据完成时调用的方法,每一次发送完成就会调用void_ondone(){print("消息传递完毕");}@overridewidgetbuild(buildcontextcontext){...}}

上面就是通过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_methodchannel=methodchannel("methodchannelplugin");@overridevoidinitstate(){_methodchannel.setmethodcallhandler((handler)=>future((){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(){futurefuture=_methodchannel.invokemethod("send",_controller.text);future.then((message){setstate((){//message是native返回的数据_resultcontent="返回值:" message;});});}@overridewidgetbuild(buildcontextcontext){...}}

上面就是通过methodchannel来进行通信的代码实现。还是比较简单的。在android端使用只需要调用methodchannelplugin的invokemethod方法即可。在flutter端使用只需要参考_sendtonative方法的实现即可。

3.4、basicmessagechannel

basicmessagechannel是一种能够在native与flutter之间互相发送消息的通信方式,它支持数据类型最多,使用范围最广。eventchannel与methodchannel的应用场景可以使用basicmessagechannel来实现,但basicmessagechannel的应用场景就不一定能够使用eventchannel与methodchannel来实现。该方式有返回值。它的使用方式如下。

首先来看android代码的实现。

//这里支持的数据类型为string。publicclassbasicmessagechannelpluginimplementsbasicmessagechannel.messagehandler{privateactivityactivity;privatebasicmessagechannelmessagechannel;staticbasicmessagechannelpluginregisterwith(flutterviewflutterview){returnnewbasicmessagechannelplugin(flutterview);}privatebasicmessagechannelplugin(flutterviewflutterview){this.activity=(activity)flutterview.getcontext();this.messagechannel=newbasicmessagechannel(flutterview,"basicmessagechannelplugin",stringcodec.instance);messagechannel.setmessagehandler(this);}@overridepublicvoidonmessage(strings,basicmessagechannel.replyreply){reply.reply("basicmessagechannelplugin收到:" s);if(activityinstanceofflutterappactivity){((flutterappactivity)activity).showcontent(s);}}voidsend(stringstr,basicmessagechannel.replyreply){messagechannel.send(str,reply);}}

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

class_myhomepagestateextendsstate{//stringcodec()为编码格式basicmessagechannel_basicmessagechannel=basicmessagechannel("basicmessagechannelplugin",stringcodec());@overridevoidinitstate(){_basicmessagechannel.setmessagehandler((message)=>future((){print(message);//message为native传递的数据setstate((){_content=message;});//给android端的返回值return"收到native消息:" message;}));_controller=texteditingcontroller();super.initstate();}//向native发送消息void_sendtonative(){futurefuture=_basicmessagechannel.send(_controller.text);future.then((message){_resultcontent="返回值:" message;});}@overridewidgetbuild(buildcontextcontext){...}}

上面就是通过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之间如何实现通信”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注恰卡编程网行业资讯频道。

展开全文
内容来源于互联网和用户投稿,文章中一旦含有米乐app官网登录的联系方式务必识别真假,本站仅做信息展示不承担任何相关责任,如有侵权或涉及法律问题请联系米乐app官网登录删除

最新文章

网站地图