一篇看懂Android与Flutter之间的通信(1)

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时返回的值,仅此一次
@Override
public 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();
}

@Override
public 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 {
EventChannel _eventChannelPlugin = EventChannel(“EventChannelPlugin”);
StreamSubscription _streamSubscription;
@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来进行通信的代码实现,调用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);
}

@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.arguments表示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端使用只需要调用MethodChannelPlugininvokeMethod方法即可。在flutter端使用只需要参考_sendToNative方法的实现即可。

3.4、BasicMessageChannel

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

首先来看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 FlutterAppActivity) {
((FlutterAppActivity) activity).showContent(s);
}
}

void send(String str, BasicMessageChannel.Reply reply) {
messageChannel.send(str, reply);
}
}

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

class _MyHomePageState extends State {
//StringCodec()为编码格式
BasicMessageChannel _basicMessageChannel =
BasicMessageChannel(“BasicMessageChannelPlugin”, StringCodec());

@override
void initState() {
_basicMessageChannel.setMessageHandler((message) => Future(() {
print(message);
//message为native传递的数据
setState(() {
_content = message;
});
//给Android端的返回值
return “收到Native消息:” + message;
}));
_controller = TextEditingController();
super.initState();
}

//向native发送消息
void _sendToNative() {
Future future = _basicMessageChannel.send(_controller.text);
future.then((message) {
_resultContent = “返回值:” + message;
});
}

@override
Widget build(BuildContext context) {…}
}

上面就是通过BasicMessageChannel来进行通信的代码实现。在Android端只需要调用BasicMessageChannelPluginsend方法就可以向flutter发送数据,BasicMessageChannel.Reply<String>是返回值的回调方法。在flutter端使用只需要参考_sendToNative方法的实现即可。

4、通信原理

从分析Android与Flutter通信的源码来看,实现还是比较简单的,都是以ByteBuffer为数据载体,然后通过BinaryMessenger来发送与接收数据。整体设计如下。

从图中可以看出,Android侧与flutter侧采用了相同的设计。前面说过通信时是异步进行的,那么线程切换在哪?其实是在系统底层实现的。在Android与Flutter通信中,系统底层屏蔽了线程切换、数据拷贝等大量复杂操作。使得Android侧与flutter侧能方便的来进行通信。

在Android侧,BinaryMessenger是一个接口,在FlutterView中实现了该接口,在BinaryMessenger的方法中通过JNI来与系统底层沟通。在Flutter侧,BinaryMessenger是一个类,该类的作用就是与类window沟通,而类window才真正与系统底层沟通。

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
15809609813)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 17
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值