前言
上篇文章说到了android 嵌入flutter后,通过自定义Activity去继承FlutterActivity,然后重写部分方法去打开一个FlutterActivity去达到我们想要的效果。这篇文章我们讲一下两者如何交互,并且同样适用于纯Flutter项目中,Flutter 和原生交互
主要是需要通过 PlantformChannel 进行交互,PlantformChannel 有三种类型,BasicMessageChannel,EventChannel,MethodChannel。具体可以看这篇文章深入理解Flutter Platform Channel
正文
BasicMessageChannel,主要用于双向传递字符串和半结构化消息传递消息
class BasicTestChannel(dartExecutor: DartExecutor) : MessageHandler<String> {
private val tag: String = "BasicTestChannel"
private val basicMessageChannel =
BasicMessageChannel(dartExecutor, "com.zww/basic", StringCodec.INSTANCE)
fun send(content: String, callback: Reply<String>) {
basicMessageChannel.send(content, callback)
Log.d(tag, "android发送flutter内容为: $content")
}
init {
basicMessageChannel.setMessageHandler(this)
}
override fun onMessage(message: String?, reply: Reply<String>) {
Log.d(tag, "android收到flutter的消息: $message")
reply.reply("android收到flutter的消息,内容为$message")
}
fun removeMessageHandler() {
basicMessageChannel.setMessageHandler(null)
}
}
onMessage是收到Flutter发送的消息的回调,然后调用reply方法可以回复 send方法是发送消息到Flutter,第二个参数是Flutter收到消息回复的回调
使用
class MyFlutterActivity : FlutterActivity() {
private lateinit var basicTestChannel: BasicTestChannel
override fun provideFlutterEngine(context: Context): FlutterEngine? {
val flutterEngine = FlutterEngine(this, null, false);
basicTestChannel = BasicTestChannel(flutterEngine.dartExecutor)
return flutterEngine
}
override fun onStart() {
super.onStart()
basicTestChannel.send("Android To Flutter", callback = BasicMessageChannel.Reply {
Log.d("basicTestChannel", "android 发送给Flutter的消息收到回复了,回复内容为:$it")
})
}
override fun shouldDestroyEngineWithHost(): Boolean {
return true
}
override fun onDestroy() {
basicTestChannel.removeMessageHandler()
super.onDestroy()
}
override fun onFlutterUiDisplayed() {
super.onFlutterUiDisplayed()
Toast.makeText(this, "onFlutterUiDisplayed", Toast.LENGTH_LONG).show()
}
}
** Flutter **
static const basicChannel =
const BasicMessageChannel("com.zww/basic", StringCodec());
@override
void initState() {
basicChannel.setMessageHandler((message) => _handlePlatform(message));
super.initState();
}
Future<String> _handlePlatform(String message) async {
print("收到Native消息:$message");
setState(() {
_counter++;
});
Future.delayed(const Duration(seconds: 3), () async {
String result =
await basicChannel.send("Flutter 发送Android内容为:Flutter To Android");
print("Flutter 发送Android消息收到回复了,回复内容为: $result");
});
return "收到Native消息:$message";
}
setMessageHandler这个异步监听就是Android发给Flutter的监听,返回值就是收到消息的回复的内容 send方法也是异步的,返回值就是Android收到消息的回复,即android里的reply返回的内容
** 流程 **
android 发送消息到Flutter,Flutter接收并返回收到消息的回复。三秒后,Flutter主动向android发送一条消息,android接收到并返回收到消息的回复。log如下
D/BasicTestChannel: android发送flutter内容为: Android To Flutter
I/flutter: 收到Native消息:Android To Flutter
D/basicTestChannel: android 发送给Flutter的消息收到回复了,回复内容为:收到Native消息:Android To Flutter
D/BasicTestChannel: android收到flutter的消息: Flutter 发送Android内容为:Flutter To Android
I/flutter: Flutter 发送Android消息收到回复了,回复内容为: android收到flutter的消息,内容为Flutter 发送Android内容为:Flutter To Android
这个混合场景举例:
android 列表页 启动Flutter的时候,传递一个itemId,并指定路由为列表详情界面,然后界面接收到这个Id去请求详情数据并加载
EventChannel
** 用于传递事件流。**
class EventTestChannel(dartExecutor: DartExecutor) : EventChannel.StreamHandler {
private var eventChannel: EventChannel = EventChannel(dartExecutor, "com.zww/event")
init {
eventChannel.setStreamHandler(this)
}
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
events?.success("1")
events?.success("2")
events?.success("3")
events?.success("4")
events?.error("1001", "This is error", "This is details")
events?.endOfStream()
events?.success("5")
}
override fun onCancel(arguments: Any?) {
}
fun removeStreamHandler() {
eventChannel.setStreamHandler(null)
}
}
class MyFlutterActivity : FlutterActivity() {
private lateinit var eventTestChannel: EventTestChannel
override fun provideFlutterEngine(context: Context): FlutterEngine? {
val flutterEngine = FlutterEngine(this, null, false);
eventTestChannel = EventTestChannel(flutterEngine.dartExecutor)
return flutterEngine
}
override fun shouldDestroyEngineWithHost(): Boolean {
return true
}
override fun onDestroy() {
eventTestChannel.removeStreamHandler()
super.onDestroy()
}
override fun onFlutterUiDisplayed() {
super.onFlutterUiDisplayed()
Toast.makeText(this, "onFlutterUiDisplayed", Toast.LENGTH_LONG).show()
}
}
**Flutter **
static const eventChannel = const EventChannel("com.zww/event");
@override
void initState() {
super.initState();
basicChannel.setMessageHandler((message) => _handlePlatform(message));
eventChannel.receiveBroadcastStream().listen(
(event) {
print("event 收到值为 $event");
},
onError: (Object error, StackTrace stackTrace) =>
print("onError: $error $stackTrace"),
onDone: () => print("onDone"),
);
}
** Log**
I/flutter: event 收到值为 1
I/flutter: event 收到值为 2
event 收到值为 3
event 收到值为 4
I/flutter: onError: PlatformException(1001, This is error, This is details)
I/flutter: onDone
MethodChannel
** 用于传递方法调用,是比较常用的 PlatformChannel**
这里就看下Flutter如何调用Android方法,以Toast为例
class ToastChannel(context: Context, dartExecutor: DartExecutor) : MethodChannel.MethodCallHandler {
private val mContext: Context = context
private val methodChannel: MethodChannel = MethodChannel(dartExecutor, "com.zww/toast")
init {
methodChannel.setMethodCallHandler(this)
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
"show" -> {
val content: String? = call.argument("content")
Toast.makeText(mContext, content, Toast.LENGTH_SHORT)
.show()
result.success(null)
}
}
}
fun removeMethodCallHandler() {
methodChannel.setMethodCallHandler(null)
}
}
class MyFlutterActivity : FlutterActivity() {
private lateinit var toastChannel: ToastChannel
override fun provideFlutterEngine(context: Context): FlutterEngine? {
val flutterEngine = FlutterEngine(this, null, false)
// 直接实例化一个新的MethodChannel
toastChannel = ToastChannel(this.context, flutterEngine.dartExecutor)
return flutterEngine
}
override fun shouldDestroyEngineWithHost(): Boolean {
return true
}
override fun onFlutterUiDisplayed() {
super.onFlutterUiDisplayed()
Toast.makeText(this, "onFlutterUiDisplayed", Toast.LENGTH_LONG).show()
}
override fun onDestroy() {
toastChannel.removeMethodCallHandler()
super.onDestroy()
}
}
** flutter **
static const toastChannel = const MethodChannel("com.zww/toast");
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
toastChannel.invokeMethod(
"show", {"content": "Flutter Module Call ToastPlugin's show method"});
}
总结
这篇文章我们能学到
- android 和Flutter是如何交互的
- 文头推荐的文章建议大家一定要去看