热文推荐:

  • 尘埃落定!清华才子王垠加入华为职级22,前阿里P10赵海平加入字节跳动,职级或为4+

  • 百度网盘“破解版”,Pandownload开发者被抓

作者:小玩童

链接:https://juejin.im/post/5e6f23eef265da574f355950

Flutter的产品定义是一个高性能的跨平台的移动UI框架,能够用一套代码同时构建出Android/iOS/Web/MacOS应用。作为一套UI框架,它不具备一些系统的接口,自然还是避免不了跟原生打交道。于是乎,它提出了名为platform channel的东西,用于flutter和原生灵活的交换数据。以下为了描述方便,用Android代指原生。

燃鹅,燃鹅,燃鹅,它只支持一些基础的数据类型和数据结构的传输,例如bool/int/long/byte/char/String/byte[]/List/Map等。

因此,当你想传输复杂点的数据,你只能包装成Map,类似这样:

await _channel.invokeMethod('initUser',{'name': 'Oscar', 'age': 16, 'gender': 'MALE', 'country': 'China'});

然后再在Android层hard code,解析出不同的key对应的不同数据。如果你是一个纯fluter项目,且以后也没有和原生打交道的打算,或者只是需要进行简单的交互,那这种做法也无可厚非。而当你的项目已经有很大的一部分原生代码或者你需要使用第三方不支持flutter的lib库的时候,就意味着你需要编写大量向上面那样的模板代码。可见效率低下,且可维护性差。这时,你会想,能传输对象就好了!

而当你想传输对象时:

抱歉,没门,只能给你一个尴尬又不是礼貌的危笑。当然,也不是不可以,我们可以在原生上层把对象序列化成json对象,然后在flutter层再把json转成flutter的对象,同样效率很差。

FIDL是什么

学过Android的应该都知道AIDL(Android Interface Defination Language),即Android接口定义语言。Android中有一种高级的跨进程通信方式——Binder,但是想要使用Binder需要了解一些Binder的机制和API,需要编写大量的模板代码。Android为了解决这个问题,尝试把使用Binder的方法做的小白一点。于是定义了AIDL,告诉开发者,你的接口文件必须按照我规定的来写,你要跨进程传输的对象必须实现Parcelable接口。然后,Android给你生成了一个Service.Stub类,偷偷的在背后把对象的序列化、反序列化的工作都给做了。开发者使用这个Stub类就能轻松上手Binder这种高级的跨进程通讯方法。(????????????我编的,差不多啦)

FIDL(Flutter Interface Defination Language)即Flutter接口定义语言,它的使命和AIDL很类似,悄悄把对象的序列化、反序列化、自动生成代码这种“脏活累活”给做了。开发者在原生代码中看到的类,能通过@FIDL注解标记,自动在Dart侧生成和原生代码中一样的类。FIDL是一面镜子,把各种原生平台的类影射到Dart中,把Dart中的类影射到各个原生平台。

少啰嗦,先看东西

首先是Java类:

public class User {String name;int age;String country;Gender gender;
}
enum Gender {MALE, FEMALE
}

Android侧

1、定义FIDL接口

@FIDL
public interface IUserService {void initUser(User user);
}

2、执行命令./gradlew assembleDebug,生成IUserServiceStub类和fidl.json文件

3、打开通道,向Flutter公开方法

FidlChannel.openChannel(getFlutterEngine().getDartExecutor(), new IUserServiceStub() {@Overridevoid initUser(User user){System.out.println(user.name + " is " + user.age + "years old!");}
}

Flutter侧

1、拷贝fidl.json文件到fidl目录,执行命令flutter packages pub run fidl_model,生成Dart接口类

2、绑定Android侧的IUserServiceStub通道

await Fidl.bindChannel(IUserService.CHANNEL_NAME, _channelConnection);

3、调用公开方法

await IUserService.initUser(User());

编译,运行,你将能在Logcat中看到Oscar is 18 years old!

FIDL使用详解

这一部分是对少啰嗦,先看东西部分的补充解释,观众姥爷们可以自行跳过。

上面的例子中的Map,一般来说,在Java中会对应一个类:

public class User {String name;int age;String country;Gender gender;
}
enum Gender {MALE, FEMALE
}

如果想让flutter传输这个对象而不用在flutter层手动去编写User这个类,以及编写fromJson/toJson方法,你可以这样做:

Android侧

1、定义一个接口,添加注解@FIDL。这个注解将告知annotationProcessor生成一些接口和类的描述文件。

@FIDL
public interface IUserService {void initUser(User user);
}

接口方法的限制如下:

  • 由于dart不支持方法重载,所以接口中不能出现同名方法

  • 参数只支持实体类,不支持回调

  • 由于JSON解码的限制,Java需要有无参构造函数

2、Android Studio点击sync,或者执行:

./gradlew assembleDebug

然后就会产生一堆json文件,如下:

这些json文件就是FIDL和类的描述文件。没错,也会同时生成User引用的Gender类的描述文件

同时,还会生成IUserService的实现IUserServiceStub。即:

  • com.infiniteloop.fidl_example.IUserService.fidl.json

  • com.infiniteloop.fidl_example.User.json

  • com.infiniteloop.fidl_example.Gender.json

  • com.infiniteloop.fidl_example.IUserServiceStub.java

限制:只能生成有强引用关系的FIDL文件,被FIDL接口强引用的类的子类如果没有被FIDL接口强引用,则不会生成相应的描述文件。

3、在合适的地方打开通道,向Flutter公开方法

IUserServiceStub userService = new IUserServiceStub() {@Overridevoid initUser(User user){System.out.println(user.name + " is " + user.age + "years old!");}
FidlChannel.openChannel(getFlutterEngine().getDartExecutor(), userService);

4、如有需要,可以在合适的地方关闭通道

FidlChannel.closeChannel(userService);

关闭的消息将通知到Flutter侧。

Flutter侧

1、进入到你的flutter项目,在lib目录下创建fidl目录,把上面的json文件拷贝到这个目录,然后执行:

flutter packages pub run fidl_model

然后就能在fidl目录下自动生成相关的dart类:

即:

  • User.dart

  • Gender.dart

  • IUserService.dart

2、绑定Android侧的IUserServiceStub通道

bool connected = await Fidl.bindChannel(IUserService.CHANNEL_NAME, _channelConnection);

_channelConnection用于跟踪IUserService通道的连接状态,通道连接成功时,会回调它的onConnected方法;通道连接断开时,会回调它的onDisconnected方法。

3、调用通道的公开方法

if (_channelConnection.connected) {await IUserService.initUser(User());
}

4、如果不再需要使用这个通道了,可以解除绑定

await Fidl.unbindChannel(IUserService.CHANNEL_NAME, _channelConnection);

当然,FIDL的功能不止于此

1、多个参数的FIDL接口

void init(String name, Integer age, Gender gender, Conversation conversation);

2、带返回值的FIDL接口

UserInfo getUserInfo();

3、支持泛型类的生成

public class User<T> {T country;
}
public class AUser<String>{}

FIDL接口:

void initUser(AUser user);

将能在dart侧生成AUser和User类,且能保持继承关系。

4、传递枚举

void initEnum0(EmptyEnum e);
String initEnum1(MessageStatus status);

5、传递集合、Map

void initList0(List<String> ids);
void initList1(Collection<String> ids);
void initList7(Stack<String> ids);
void initList10(BlockingQueue ids);

6、传递复杂对象。继承、抽象、泛型、枚举和混合类,来一个打一个。

当然,FIDL能做的不止于此

现在,FIDL项目只实现了从Dart侧调用Android侧的方法。还有以下工作要做:

  • Android侧调用Dart侧的方法

  • 其它平台和Flutter方法的互相调用

  • EventChannel,EventChannel本质上是可以通过MethodChannel实现的,问题不大

搞定了对象传输,这些问题,都是小case啦。

对于对象的序列化和反序列化

为了能满足大佬们的定制化需求,我分别在Java侧和Flutter侧定义了序列化/反序列化的接口类。

Java:

public interface ObjectCodec {List<byte[]> encode(Object... objects);<T> T decode(byte[] input, TypeLiteral<T> type);
}

Dart:

abstract class ObjectCodec {dynamic decode(Uint8List input);List<Uint8List> encode(List objects);
}

目前使用的是JsonObjectCodec,经过JSON的编解码,性能会稍差。后面还希望和小伙伴们一起努力,实现更高效的编解码。

项目进度

上述提到的功能,只要是从Flutter侧调用Java侧的方法相关的,大部分都已经实现了。

我做了一个Demo,模拟了一个在Android侧依赖了IM(即时通讯)SDK,需要在Flutter侧聊天、获取消息、发消息的场景。以下是Demo的截图:

1、首页,点击按钮调用Android侧方法,开启聊天服务

2、聊天页面

3、发一条消息给Lucy并获取和Lucy的聊天记录

4、调用Android侧方法发送N条消息给Wilson并获取聊天记录

最后

上次做开源项目已经是3年前了,那是一个Android原生刷新控件,TwinklingRefreshLayout,github 3.7k stars。后来由于工作的原因,整天跟Android Framework、C/C++打交道,精力也都是放到了公司的业务上,也没有时间和精力维护下去。

那么今天我想发布的这个Flutter开源项目,是想通过社区的力量,和大家一起把项目维护下去。我在GayHub上建立了一个组织,github.com/flutterFIDL。FIDL的代码在这里,github.com/flutterFIDL…。大家记得投币、点赞、收藏,一键3连(大家如果觉得这个项目能很好解决跨平台通信问题,给个star可以嘛????)。阿不,我需要一个团队跟我一起发展这个项目,希望你熟悉Flutter开发,了解Android和Java开发,热爱开源,熟悉Flutter+iOS / Flutter + Web其中的一种,并有相关项目经历,加我vx: w354850839。

项目地址:https://github.com/flutterFIDL

强力推荐:一个好用的Flutter与原生应用通讯的开源框架!相关推荐

  1. Maplab:一个用于视觉惯性建图和定位研究的开源框架

    摘要 鲁棒且精确的视觉惯性估计是当今机器人领域的重要挑战.能够用先验地图(prior map)进行定位(localize)并获得准确且无漂移的姿态估计,可以推动该系统的适应性.然而,目前大多数可用的解 ...

  2. Flutter开发Flutter与原生OC、Java的交互通信-2(48)

    我们上一篇主要讲了Flutter与原生OC.Java的交互通信的机制:平台通道 只实现了Flutter 主动调用OC.Java的方向的通信.并没有实现OC.Java端主动调用Flutter的实现.这里 ...

  3. Flutter开发Flutter与原生OC、Java的交互通信-1(47)

    我的文章讲过:(0085)iOS开发之OC与JS交互高级用法(JavaScriptCore) 前言:我们知道OC 在UIWebView 加载 H5中,常常需要OC 与 H5 之间进行交互调用.采取的方 ...

  4. 包红b2c模块 flutter与原生交互

    一.flutter提供的FlutterMethodChanel与原生(ios&android)进行交换 flutter与原生交互图: ios注册flutter调用通道 //oc 注册flutt ...

  5. android调用flutter aar_Flutter原生混合开发

    混合开发简介 使用Flutter从零开始开发App是一件轻松惬意的事情,但对于一些成熟的产品来说,完全摒弃原有App的历史沉淀,全面转向Flutter是不现实的.因此使用Flutter去统一Andro ...

  6. 一个很棒的Flutter学习资源列表

    目录 文章 一开始 HOWTO文档 网站/博客 高级 视频 组件 演示 UI 材料设计 图片 地图 图表 导航 验证 文字和富文本 分析.流量统计 自动构建 风格样式 媒体 音频 视频 语音 存储 获 ...

  7. flutter和原生交互

    一.Flutter中使用Android Studio打开原生文件 选中Android目录--右键--选中flutter---Open for Editing in Android Studio 问题1 ...

  8. Flutter与原生通信

    -- Flutter作为一个跨平台框架,一经问世,便受到众多开发的追捧,发展至今相信已经有很多公司或个人将其加入自己的项目,进行混合开发,那么FLutter如何与原生通信呢? -- 本次就以Andro ...

  9. 教你如何使用Flutter和原生App混合开发

    点击上方 "程序员小乐"关注, 星标或置顶一起成长 每天凌晨00点00分, 第一时间与你相约 每日英文 Things in this world are temporary. If ...

最新文章

  1. 安装mysql 1045_mysql安装出现error Nr.1045
  2. 岗位内推 | 微软亚洲互联网工程院自然语言处理组招聘
  3. Java Web编程的主要组件技术——Hibernate入门
  4. 如何安装并启动django
  5. 【渝粤教育】 国家开放大学2020年春季 1080工程数学(本) 参考试题
  6. Windows学习总结(13)——各品牌电脑进入BIOS按键汇总
  7. Windows Embedded Standard 7 剪裁随笔
  8. HDU6383 p1m2
  9. WPS文字2013利用绘图工具中的形状裁剪出各式各样的图片
  10. 计算机应用基础教程在线阅读,【精品】计算机应用基础教程
  11. maven命令打jar包
  12. 我的Android进阶之旅------android中一些特殊字符(如:←↑→↓等箭头符号)的Unicode码值
  13. MySQL服务器配置优化(读书笔记)
  14. web_dynpro_ALV:(包ZLYTEST2)(alv 的事件只需注意一个R_PARAM就哦了)
  15. repo init报错error.GitError: manifests rev-list (u'^2736dfd46e8a30cf59a9cd6e93d9e56e87021f2a', 'HEAD',
  16. Pythonnbsp;异常处理
  17. 智能家居控制模拟套件
  18. 浏览器地址栏javascript
  19. 【C#】游戏客户端编程
  20. android sd卡目录查看,Android sd卡目录详解

热门文章

  1. c语言编译器mingw——常用编译命令
  2. [转载]巧改上传图片格式的 Protel 99SE 视频教程
  3. 如何 修改服务器控件的text,设置TextBox控件的TextMode属性
  4. Mac开启root权限
  5. FAE新手上路(三)
  6. php表单提交serialize,jQuery使用serialize(),serializeArray()方法取得表单数据
  7. 计算基本统计值,输出一组数据的平均值,方差,众数和中位数
  8. 叹服,阿里自述 SpringCloud 微服务:入门 + 实战 + 案例,一网打尽
  9. 计算机硕士专业怎样出论文,计算机专业硕士论文参考文献集 计算机专业硕士参考文献怎么写...
  10. Active Directory 01 - “史上最全”测试环境搭建模板