flutter 和native之间的几种通信场景:
Flutter和Native的通信是通过Channel来完成的。
消息使用Channel(平台通道)在客户端(UI)和主机(平台)之间传递,如下图所示:
Flutter定义了三种不同类型的Channel:
- BasicMessageChannel:用于传递字符串和半结构化的信息,持续通信,收到消息后可以回复此次消息,如:Native将遍历到的文件信息陆续传递到Dart,在比如:Flutter将从服务端陆陆续获取到信息交个Native加工,Native处理完返回等;
- MethodChannel:一次性通信:如Flutter调用Native拍照;
- EventChannel: 用于数据流(event streams)的通信,持续通信,收到消息后无法回复此次消息,常用于Native向Dart的通信。
这三种类型的类型的Channel都是全双工通信,即A <=> B,Dart可以主动发送消息给platform端,并且platform接收到消息后可以做出回应,同样,platform端可以主动发送消息给Dart端,dart端接收数后返回给platform端。
1.EventChannel
EventChannel是一种native向flutter发送数据的单向通信方式,flutter无法返回任何数据给native。主要用于native向flutter发送手机电量变化、网络连接变化、陀螺仪、传感器等。它的使用方式如下。
Android 端:
如图所示,分为上下两部分,Android端通过输入内容,传递给flutter页面,且展示出来。
首先来看Android的代码
创建一个eventChannelPlugin对象。
public class EventChannelPlugin implements EventChannel.StreamHandler {
private static final String TAG = EventChannelPlugin.class.getSimpleName();
private EventChannel.EventSink eventSink;
private Activity activity;
private EventChannelPlugin(FlutterView flutterView) {
this.activity = (Activity) flutterView.getContext();
}
public static EventChannelPlugin registerWith(FlutterView flutterView) {
EventChannelPlugin plugin = new EventChannelPlugin(flutterView);
new EventChannel(flutterView, "EventChannelPlugin").setStreamHandler(plugin);
return plugin;
}
//第一个参数为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;
}
public void send(Object params) {
if (eventSink != null) {
eventSink.success(params);
}
}
public void sendError(String str1, String str2, Object params) {
if (eventSink != null) {
eventSink.error(str1, str2, params);
}
}
}
然后在Android的主界面里开始初始化界面,然后初始化eventchannelplugin 对象,且记得把flutterview加载到Android的原生项目里。
// 注意eventchannel是对应Flutter那边的页面;
FlutterView flutterView = Flutter.createView(this, getLifecycle(), "eventchannel");
eventChannelPlugin = EventChannelPlugin.registerWith(flutterView);
mContent.removeAllViews();
mContent.addView(flutterView);
//最后发送内容出去
String inputResult = mInput.getText().toString().trim();
eventChannelPlugin.send(inputResult);
flutter 端的逻辑
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class EventChannelPage extends StatefulWidget {
@override
_EventChannelPageState createState() => _EventChannelPageState();
}
class _EventChannelPageState extends State<EventChannelPage> {
// 初始化对象 EventChannelPlugin 对象Android的eventchannel的类名
EventChannel _eventChannelPlugin = EventChannel("EventChannelPlugin");
StreamSubscription _streamSubscription;
String nativeResult = '';
@override
void initState() {
// TODO: implement initState
super.initState();
_streamSubscription = _eventChannelPlugin
//["abc", 123, "你好"]对应着Android端onListen方法的第一个参数,可不传值
.receiveBroadcastStream(["abc", 123, "你好"]).listen(_onToDart,
onError: _onToDartError, onDone: _onDone);
}
@override
Widget build(BuildContext context) {
return Container(
child: Text(
"原生的数据:$nativeResult",
style: TextStyle(fontSize: 22),
),
);
}
@override
void dispose() {
if (_streamSubscription != null) {
_streamSubscription.cancel();
_streamSubscription = null;
}
super.dispose();
}
//native端发送正常数据
void _onToDart(message) {
setState(() {
nativeResult = message;
print(message);
});
}
//当native出错时,发送的数据
void _onToDartError(error) {
print(error);
}
//当native发送数据完成时调用的方法,每一次发送完成就会调用
void _onDone() {
print("消息传递完毕");
}
}
BasicMessageChannel
android端代码:
package com.example.flutter_android.channel;
import android.app.Activity;
import com.example.flutter_android.BasicMsgActivity;
import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.StringCodec;
import io.flutter.view.FlutterView;
public class BasicMessagePlugin implements BasicMessageChannel.MessageHandler<String> {
private Activity activity;
private BasicMessageChannel<String> messageChannel;
public static BasicMessagePlugin registerWith(FlutterView flutterView) {
return new BasicMessagePlugin(flutterView);
}
/*BasicMessageChannel
* flutterView
* initRoute 初始化路由,可以指定页面
* 编码器
*/
private BasicMessagePlugin(FlutterView flutterView) {
this.activity = (Activity) flutterView.getContext();
this.messageChannel = new BasicMessageChannel<String>(flutterView, "BasicMessageChannelPlugin", StringCodec.INSTANCE);
messageChannel.setMessageHandler(this);
}
@Override
public void onMessage(String s, BasicMessageChannel.Reply<String> reply) {
// 对此次发送的消息立即回复
reply.reply("BasicMessageChannelPlugin收到:" + s);
if (activity instanceof BasicMsgActivity) {
((BasicMsgActivity) activity).showContent(s);
}
}
/**
* 定义发送信息方法
*/
public void send(String str, BasicMessageChannel.Reply<String> reply) {
messageChannel.send(str, reply);
}
}
activity界面
// 初始化BasicMessagePlugin对象
final FlutterView flutterView = Flutter.createView(this, getLifecycle(), "basicmessage");
basicMessagePlugin = BasicMessagePlugin.registerWith(flutterView);
mContent.removeAllViews();
mContent.addView(flutterView);
Android端发送消息给Flutter
basicMessagePlugin.send("here is Native",new BasicMessageChannel.Reply(){
@Override
public void reply(Object o) {
mResult.setText("来自于flutter立即回复 :"+o.toString());
}
});
flutter端接收消息
class _BasicMessagePageState extends State<BasicMessagePage> {
//StringCodec()为编码格式
BasicMessageChannel<String> _basicMessageChannel =
BasicMessageChannel("BasicMessageChannelPlugin", StringCodec());
String _content;
@override
void initState() {
// TODO: implement initState
super.initState();
_basicMessageChannel.setMessageHandler((message) => Future<String>(() {
print(message);
//message为native传递的数据
setState(() {
_content = message;
});
//可以对此次消息立即回应Android端的返回值
return "I am flutter,I Received : ($message)";
}));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("this is basicMessager"),
),
body: Column(
children: <Widget>[
Column(
children: <Widget>[
Text(
"来源于native :$_content",
style: (TextStyle(fontSize: 15)),
),
RaisedButton(
child: Text("发送数据给Native"),
onPressed: ()=> _sendMsg(),
),
],
),
],
),
);
}
_sendMsg() {
_basicMessageChannel.send("here is flutter!");
}