首页 欧洲联赛正文

猎户座,一篇看懂Android与Flutter之间的通讯,凤凰古城在哪

Flutter作为一种跨渠道解决方案,经常会作为一个模块嵌入到原生Android与iOS运用中,Flutter与Android原生端的通讯必不可少。所以本文就来叙述一下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通讯的一些根底知识,下面就进入正题,来看A簿本全彩ndroid怎么与flutter进行通讯。

Android与Flutter之间的通讯共有四种完结办法。

  1. 因为在初始化flutter页面时会传递一个字符串——route,因而咱们就能够拿route来做文章,传递自己想要传递的数据。该种办法仅支撑单向数据传递且数据类型只能为字符串,无回来值。
  2. 经过EventChannel来完结,EventChannel仅支撑数据单向传递,无回来值。
  3. 经过MethodChannel来完结,MethodChannel支撑数据双向传递,有回来值。
  4. 经过BasicMess小村渔色ageChannel来完结,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猎户座,一篇看懂Android与Flutter之间的通讯,凤凰古城在哪: key);
@override
Widget 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 fi吴胜焕nal String TAG = EventChannelPlugin.class.getSimpleName();
private EventChannel.EventSink eventSink;
private Activity activity;
static EventChan猎户座,一篇看懂Android与Flutter之间的通讯,凤凰古城在哪nelPlugin 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时回来的值,猎户座,一篇看懂Android与Flutter之间的通讯,凤凰古城在哪仅此一次
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
this.eventSink = eventSink;
Log.i(TAG, "eventSink:" + event陶成德Sink);
Log.i(TAG, "Object:" + o.toString());
Toast.makeText(activity, "onListen——obj:" + o, Toast.LENGTH_SHORT).show();
}
@Override
public void onCancel(Object o) {
Log.i(TAG, "onCancel:" + o.toString());
Toas罗恩达尔t.makeText(activity, "onCancel——obj:" + o, Toast.LENGTH_SHORT).show();
this.eventSink = null;
}
}

笔者对Android端代码做了一个简略的封装,仍是很好了解的。下面就来看flutter代码完结。

class _MyHomePageState extends State {
EventChannel _eventChannelPlugin = EventChannel("EventChannelPlugin");
StreamSubscription _strecosarcsinxamSubscription;
@override
void initState() {
_streamSubscription = _eventChannelPlugin
//["abc", 123, "你好"]对应着Android端onListen办法的第一个参数,可不传值
.receiveBroadcastStream(["abc", 123, "你好"])
.listen(_onToDart, onError: _onToDartError, onDone: _onDone);
super.initState();
}
@override
void 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() {
print("音讯传递结束");
}
@override
Widget build(BuildContext context) {...}
}

上面便是经过EventChannel来进行通讯的代码完结,调用EventChannelPlugin的send办法就能给flutter发送数据。

3.3、MethodChannel

MethodChannel是一种native与flutter之间相互发送数据的通讯办法,望文生义,经过MethodChannel就能调用native与flutter中相对应的办法,该种办法有回来值。它的运用办法如下。

首要来看Android端的代码完结。

public class MethodChannelPlugin 猎户座,一篇看懂Android与Flutter之间的通讯,凤凰古城在哪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.getCo宋依临ntext猎户座,一篇看懂Android与Flutter之间的通讯,凤凰古城在哪(), channel);
channel.setMethodCallHandler(methodChannelPlugin);
return methodChannelPlugin;
}
private MethodChannelPlugin(Activity activity, MethodChannel channel) {
this.activ修身别传ity = 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);
}
@Override
public 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 {
MethodChannel _methodChannel = MethodChannel("MethodChannelPlugin");
@override
void initState() {
_methodChannel.setMethodCallHandler((handler) => Future(() {
print("_methodChannel:${handler}");
//监听native发送的办法名及参数
switch (handler.method) {
case "send":
_send(handler.arguments);//handler.argu林景荣ments表明native传递的办法参数
break;
}
}));
super.initState();
}
//native调用的flutter办法
void _send(arg) {
setState(() {
_content = arg;
});
}
String _resultContent = "";
//flutter调用native的相应办法
void _sendToNative() {
Future future =
_methodChannel.invokeMethod("send", _controller.text);
future.then((message) {
setState(() {
//message是native回来的数据
_resultContent = "回来值:" + message;
});
});
}
@override
Widget build(BuildContext context) {...}
}

上面便是经过MethodChannel来进行通讯的代码完结。仍是比较简略的。在Android端运用只猎户座,一篇看懂Android与Flutter之间的通讯,凤凰古城在哪需求调用MethodChannelPlugin的invokeMethod办法即可。在flutter端运用只需求参阅_sendToNative办法的完结即可。

3.4、BasicMessageChannel

BasicMessageChannel是一种能够在native与flutter之间相互发送音讯的通讯办法,它支撑数据类型最多,运用范围最广。EventChannel与MethodChannel的运用场景能够运用BasicMessageChannel来完结,但BasicMessageChannel的运用场景就不必定能够运用EventChannel与MethodChannel来完结。该办法有回来值。它的运用办法如下。

首要来看Android代码的完结。

//这儿支撑的数据类型为String。
public class BasicMessageChannelPlugin implements BasicMessageChannel.MessageHandler {
private Activity activity;
private BasicMessageChannel messageChannel;
static BasicMessageChannelPlugin registerWith(FlutterView flutterView) {
return new BasicMessageChannelPlugin(flutterView);
}
private BasicMessageChannelPlugin(FlutterView flutterView) {
this.activity = (Activity) flutterView.getContext();
this.messageChannel = new BasicMessageChannel(flutterView, "BasicMessageChannelPlugin", StringCodec.INSTANCE);
messageChannel.setMessageHandler(this);
}
@Override
public void onMessage(String s, BasicMessageChannel.Reply reply) {
reply.reply("BasicMessageChannelPlugin收到:" + s);
if (activity instanceof Flutte律组词rAppActivity) {
((FlutterAppActivity) activity).showContent(s);
}
}
void send(String str, BasicMessageChannel.Reply reply) {
messageChannel.send(str, reply);
}
}

笔者对Android端代码做了一个简略的封装,仍是很好了解的。下面就来看flutter代码完结。

class _MyHomePageState extends State {
//StringCodec()为编码格局
BasicMessageChannel _basicMessageChannel =
BasicMessageChann刘忠巍el("BasicMessageChannelPlugin", StringCodec());
@override
void initState() {
_basicMessageChannel.setMessageHandler((message) => Future(() {
print(message);
//message为native传递的数据
setState(() {
_content = message;
});
//给Android端的回来值
return "收到Native音讯:" + message;
}));
_contro心海集团鲍世超被拘留ller = TextEditingController();
super.initState();
}
//向native发送音讯
void _sendToN豁拉子ati猎户座,一篇看懂Android与Flutter之间的通讯,凤凰古城在哪ve() {
Future future = _basicMessageChannel.send(_controller.text);
future.then((message) {
_resultContent = "回来值:" + message;
});
}
@override
Widget build(BuildContext context) {...}
}

上面便是经过BasicMessageChannel来进行通讯的代码完结。在Android端只需求调用BasicMessageChannelPlugin的sendrline是什么意思办法就能够向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才真正与体系底层交流。

关于通讯的底层完结能够去阅览闲鱼的技能文章——深化了解Flutter Platform Channel,这篇文章很好的叙述了Flutter与Native通讯的体系底层原理。

5、总结

在Android与Flutter混合开发形式下,相互之间通讯的场景必定不会少。了解Android与Flutter之间通讯的各种办法及运用,有助于选用合理的办法来完结。

最终

假如你看到了这儿,觉得文章写得不错就给个赞呗?假如你觉得那里值得改善的,请给我留言。必定会仔细查询,批改缺乏。谢谢。

最终针对Android程序员,我这边给我们整理了一些材料,包含不限于高档UI、功能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技能;希望能协助到我们,也节约我们在网上查找材料的时刻来学习,也能够共享动态给身边老友一同学习!

需求打开的架构学习笔记导图的能够:后台私信回复“安卓材料”免费获取~

版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。