强力推荐:一个好用的Flutter与原生应用通讯的开源框架!
链接:https://juejin.im/post/5e6f23eef265da574f355950
await _channel.invokeMethod('initUser',
{'name': 'Oscar', 'age': 16, 'gender': 'MALE', 'country': 'China'});
FIDL是什么
少啰嗦,先看东西
首先是Java类:
public class User {
String name;
int age;
String country;
Gender gender;
}
enum Gender {
MALE, FEMALE
}
1、定义FIDL接口
@FIDL
public interface IUserService {
void initUser(User user);
}
2、执行命令./gradlew assembleDebug
,生成IUserServiceStub类和fidl.json文件
3、打开通道,向Flutter公开方法
FidlChannel.openChannel(getFlutterEngine().getDartExecutor(), new IUserServiceStub() {
@Override
void initUser(User user){
System.out.println(user.name + " is " + user.age + "years old!");
}
}
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() {
@Override
void 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>{}
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、传递复杂对象。继承、抽象、泛型、枚举和混合类,来一个打一个。
-
Android侧调用Dart侧的方法 -
其它平台和Flutter方法的互相调用 -
EventChannel,EventChannel本质上是可以通过MethodChannel实现的,问题不大
为了能满足大佬们的定制化需求,我分别在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并获取聊天记录