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

不得不看的Flutter与Android混合开发一文中讲述了Android项目如何导入flutter模块,但有一个问题,就是它们之间还不能互相通信,但这又是非常必要的。所以本文就来讲述一下Android如何与flutter进行通信。

1、架构概述

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

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

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

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

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

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

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

Dart Android iOS
null null nil (NSNull when nested)
bool java.lang.Boolean NSNumber numberWithBool:
int java.lang.Integer NSNumber numberWithInt:
int, if 32 bits not enough java.lang.Long NSNumber numberWithLong:
int, if 64 bits not enough java.math.BigInteger FlutterStandardBigInteger
double java.lang.Double NSNumber numberWithDouble:
String java.lang.String NSString
Uint8List byte[] FlutterStandardTypedData typedDataWithBytes:
Int32List int[] FlutterStandardTypedData typedDataWithInt32:
Int64List long[] FlutterStandardTypedData typedDataWithInt64:
Float64List double[] FlutterStandardTypedData typedDataWithFloat64:
List java.util.ArrayList NSArray
Map java.util.HashMap NSDictionary

关于编解码器,Android端提供了以下四种。

  • BinaryCodec:是最简单的一种编解码器,其返回值类型与入参的类型相同,均为二进制格式(ByteBuffer)。由于BinaryCodec在编解码过程中什么都没做,只是原封不动的将二进制数据返回。所以传递的数据在编解码时会免于拷贝,这种方式在传递的数据量比较大时很有用。比如从Android侧传入一张图片到Flutter侧显示。
  • StandardMessageCodec:是BasicMessageChannel的默认编解码器,支持基础数据类型、列表及字典等。在编码时会先将数据写入到ByteArrayOutputStream流中,然后再将该流中的数据写入到ByteBuffer中。在解码时,直接从ByteBuffer中读取数据。
  • StandardMethodCodec:是基于StandardMessageCodec的封装。是MethodChannelEventChannel的默认编解码器。
  • StringCodec:是用于字符串与二进制数据之间的编解码,其编码格式为UTF-8。在编码时会将String转成byte数组,然后再将该数组写入到ByteBuffer中。在解码时,直接从ByteBuffer中读取数据
  • JSONMessageCodec:内部调用StringCodec来实现编解码。
  • JSONMethodCodec:基于JSONMessageCodec的封装。可以在MethodChannelEventChannel中使用。

ByteBuffer是Nio中的一个类,顾名思义——就是一块存储字节的区域。它有两个实现类——DirectByteBufferHeapByteBufferDirectByteBuffer是直接在内存中开辟了一块区域来存储数据,而HeapByteBuffer是在JVM堆中开辟一块区域来存储数据,所以要想数据在DirectByteBuffer中与HeapByteBuffer互通,就需要进行一次拷贝。关于ByteBuffer的更多内容可以去阅读Java NIO 的前生今世 之三 NIO Buffer 详解这篇文章。

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(
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值