千家信息网

Android与Flutter之间如何实现通信

发表于:2025-11-13 作者:千家信息网编辑
千家信息网最后更新 2025年11月13日,这篇"Android与Flutter之间如何实现通信"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一
千家信息网最后更新 2025年11月13日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端提供了以下几种。

  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代码。

//第三个参数可以换成我们想要字符串。 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);  @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 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来进行通信的代码实现,调用EventChannelPlugin的send方法就能给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端使用只需要调用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 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端只需要调用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之间如何实现通信"这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注行业资讯频道。

数据 方法 通信 方式 代码 消息 支持 之间 类型 解码器 还是 内容 字符 字符串 就是 平台 参数 封装 二进制 底层 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 西安慧科网络技术有限公司 网络安全博览会要票吗 计算机网络技术 女生学 服务器显示链接栏后如何切换界面 数据库系统的分区 乌鲁木齐纯软件开发企业 浪潮服务器蜂鸣器响两秒隔一秒 caldav 服务器 一台服务器搭建零客户机解决方案 acdsee数据库怎么设置 控件连接数据库 享专属服务器抢票啥意思 软件开发培训都有哪些 网络安全分多少期 数据库技术与应用资料 网络安全青年担当班会 软件开发 框架 甘肃浪潮服务器维修系统虚拟主机 服务器连接用户数量设置 加密通讯软件开发 成都水滴互联网科技公司 北京服务器运维服务云空间云主机 acdsee数据库怎么设置 工业网络技术专业有编程吗 新型电力下的网络安全 广州日立电梯服务器密码 数据库字典设计 查询数据库判断是否有数据 数据库输错了一行怎么重新开始 全国职工网络安全创新发展大会
0