1.Flutter Module < ---- init Params ----Native Module
2.Flutter Module <---- ---- Native Module
3.Flutter Module ---- > Native Module
4.Flutter Module < ---- > Native Module
所谓“平台特定”或“特定平台”,平台指的就是指Flutter运行的平台,如Android或IOS,可以认为就是应用的原生部分。所以,平台通道正是Flutter和原生之间通信的桥梁,它也是Flutter插件的底层基础设施。
Flutter使用了一个灵活的系统,允许您调用特定平台的API,无论在Android上的Java或Kotlin代码中,还是iOS上的ObjectiveC或Swift代码中均可用。
Flutter与原生之间的通信依赖灵活的消息传递方式:
使用平台通道在Flutter(client)和原生(host)之间传递消息,如下图所示:
当在Flutter中调用原生方法时,调用信息通过平台通道传递到原生,原生收到调用信息后方可执行指定的操作,如需返回数据,则原生会将数据再通过平台通道传递给Flutter。值得注意的是消息传递是异步的,这确保了用户界面在消息传递时不会被挂起。
在客户端,MethodChannel API 可以发送与方法调用相对应的消息。 在宿主平台上,MethodChannel
在Android API 和 FlutterMethodChannel iOS API可以接收方法调用并返回结果。这些类可以帮助我们用很少的代码就能开发平台插件。
平台通道使用标准消息编/解码器对消息进行编解码,它可以高效的对消息进行二进制序列化与反序列化。由于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 |
1.BasicMessageChannel: 用于传递字符串和半结构化的信息,维持通信,接收到消息后可以回复此次消息。
比如“:Native将遍历到的文件陆续传递到Dart,再比如:Flutter将从服务端陆续获取到的信息交给Native加工,Native处理完后返回等。
2.MethodChannel: 用于传递方法调用(method invocation) 一次性通信:如Flutter调用Native拍照。
3.EventChannel:用于数据流(event streams)的通信,持续通信,收到消息后无法回复此次消息,通常用于Native向Dart的通信,如:电量的变化、网络连接的变化、传感器等等。
以上3种Channel都是全双工通信,即A <==> B,Dart可主动发送消息给platform端,并且platform接收到消息后可以做出反应。同样,platform端可以主动发送消息给Dart端,Dart端接收数据后返回给platform端。
Dart端:
//构造方法原型:
const BasicMessageChannel(this.name,this.codec);
String name : Channel 的名字,要和Native端保持一致。
MessageCodec
Dart端到platform传递的过程种是以2进制的形式传递的,比如发送String类型数据,Dart通过编解码器将数据变成2进制,在Android端通过这个编解码器解码为String,Android端才能进行使用。
//setMessageHandler方法的原型
void setMessageHandler(Future handler(T message))
Flutter
Dart端:在创建好BasicMessageChannel后,如果要让其接收Native发送来的消息,则需要调用它的setMessageHandler方法为其设置一个消息处理器。
//send方法原型
Future send(T message)
T message: 要传递给Native的具体信息。
Future
在创建好BasicMessageChannel后,如果要向Native发送消息,可以调用它的send方法向Native传递数据。
这个方法接收一个Future的返回值,所以通信是异步的。然后发送消息的同时会返回一个消息。也就是说Native端收到一个消息之后可以给Dart端回传这个消息的处理结果等。
import 'package: flutter/services.dart'
...
static const BasicMessageChannel _basicMessageChannel =
const BasicMessageChannel('BasicMessageChannelPlugin',StringCodec());
...
//使用BasicMessageChannel接受来自Native的消息,并向Native回复
_basicMessageChannel
.setMessageHandler((String message) => Future(){
setState((){
showMessage = message;
});
return "收到native的消息:" +message;
});
//使用BasicMessageChannel向Native发送消息,并接受Native的回复
String response;
try{
response = await _basicMessageChannel.send(value);
} on PlatformException catch(e) {
print(e);
}
...
Native端:
BasicMessageChannel(BinaryMessenger messenger,String name ,MessageCodec codec)
BinaryMessenger :消息信使,是消息的发送与接收的工具。
String name : 是channel的名字,也是唯一的标识符。
MessageCodec
1.BinaryCodec: 最简单的一种Codec,因为其返回值类型和入参的类型相同,均为2进制格式。实际上,BinaryCodec在编译的过程中什么都没有做,只是原封不动的将2进制数据消息返回而已。但在某种情况下它非常有用,比如使用t它可以使传递内存数据块时在编解码阶段免于内存拷贝。
2. StringCodec : 用于字符串和2进制数据之间的编解码,其编码格式为UTF-8
3. JSONMessageCodec: 用于基础数据与2进制之间的编解码,其支持基础数据类型以及列表、字典。其在IOS端使用了NSJSONSerialzation作为序列化工具,在Android端使用了其自定义的JSONUtil与StringCodec作为序列化工具。
4.StandardMessageCodec: 是BasicMessageChannel的默认的编解码器,其支持基础类型、2进制数据、列表、字段、其工作原理。
void setMessageHandler(BasicMessageChannel.MessageHandler handler)
在创建好BasicMessageChannel后,如果让其接收Dart发来的消息,则需要调用它的setMessageHandler方法为其设置一个消息处理器。
public interface MessageHandler{
void onMessage(T var1,BasicMessageChannel.Reply var2);
}
onMessage(T var1,BasicMessageChannel.Reply
void send(T message)
void send(T message ,BasicMessageChannel.Reply callback)
T message: 要传递给Dart的具体信息。
BasicMessageChannel.Reply
在创建好BasicMessageChannel后,如果要向dart端发送消息,可以调用它的send方法向Dart传递数据。
public class BasicMessageChannelPlugin implements BasicMessageChannel.MessageChannel,BasicMessageChannel.Reply{
private final Activity activity;
private final BasicMessageChannel messageChannel;
static BasicMessageChannelPlugin registerwith(FlutterView flutterView){//flutterView就是一个BinaryMessage
return new BasicMessageChannelPlugin (flutterView);
}
private BasicMessageChannelPlugin (FlutterView flutterView){
this.activity = (Activity) flutterView.getContext();
this.messageChannel = new BasicMessageChannel<>(flutterView,'BasicMessageChannelPlugin',StringCodec.INSTANCE);
//设置消息处理器,处理来自Dart的消息
messageChannel.setMessageHandler(this);
}
@Override
public void onMessage(String s , BasicMessageChannel.Reply reply){//处理Dartt
reply.reply("BasicMessageChannel收到:"+s);//可通过reply进行回调
if(activity instanceof IShowMessage){
( (IShowMessage) activity).onShowMessage(s);
}
Toast.makeText(activity,s,Toast.LENGTH_SHORT).show();
}
///向Dart发送消息,并接收dDart的反馈
void send(String message ,BasicMessageChannel.Reply callback){
messageChannel.send(message,callback);
}
@Override
public void reply(String s){
}
}
Dart端:
const MethodChannel(this.name,[this.codec = const StandardMethodCodec()]);
String name : Channel 的名字,和Native端保持一致。
MethodCodec codec : 消息的编解码器,默认是StandardMethodCodec ,和Native端保持一致。
Future inbokeMethod(String method,[dynamic arguments])
String method: 要调用的Native的方法名。
dynamic arguments:要调用的Native方法传递的参数,可不传(dart语法:可选参数)
import 'package:flutter/services.dart';
...
static const MethodChannel _methodChannelPlugin =
const MethodChannel('MethodChannelPlugin');
...
String response;
try{
response = await _methodChannelPlugin .invokeMethod('send',value);
} on PlatformException catch (e) {
print(e);
}
...
Native端:
MethodChannel(BinaryMessenger messenger,String name)
MethodChannel(BinaryMessenger messenger,String name,MethodCodec codec)
BinaryMessenger messenger: 消息的信使。
String name : channel的名字
MethodCodec codec : 用作MethodChannel的编解码器。
setMethodCallHandler(@Nullable MethodChannel.MethodCallHandler handler)
@Nullable MethodChannel.MethodCallHandler handler:息处理器,配合BinaryMessenger完成消息的处理。
在创建好methodChannel后,需要调用它的setMessageHandler方法为其设置一个消息处理器,方便能接收来自Dart的消息。
public interface MethodCallHandler {
void methodCall(MethodCall var1,MethodChannel.Result var2);
}
MethodCall var1,MethodChannel.Result var2:用于接收消息,call是消息内容,它的2个成员遍历String类型,call.method表示调用的方法名,Object类型的call.arguments表示调用方法所传递的入参。MethodChannel.Result result是回复此消息的回调函数提供了result.success,result.error,result.notImplemented方法调用。
public class MehthodChannelPlugin implements MethodCallHandler{
private final Activity activity;
public static void registerwith(FlutterView flutterView){
MethodChannel channel = new MethodChannel (flutterView,"MehthodChannelPlugin");
MehthodChannelPlugin instance = new MehthodChannelPlugin((Activity) flutterView.getContext());
channel.setMethodCallHandler(instance);
}
private MehthodChannelPlugin(Activity activity){
this.activity = activity;
}
@Override
public void onMethodCall(MethodCall call ,Result result){
switch(call.method){//处理来自Dart的方法调用
case "showMessage":
showMessage(call.arguments);
result.success("MehthodChannelPlugin收到:" + call.arguments);//返回结果给Dart
break;
default:
result.notImplemented();
}
}
//展示来自Dart的数据。
private void showMessage(String arguments){
if(activity instanceof IShowMessage){
((IShowMessage) activity).onShowMessage(arguments);
}
Toast.makeText(activity,argumemts,Toast.LENGTH_SHORT).show();
}
}
Dart端:
const EventChannel(this.name,[this.codec = const StandardMethodCodec()]);
String name : Channel 的名字,和Native端保持一致。
MethodCodec codec : 消息的编解码器,默认是StandardMethodCodec ,和Native端保持一致。
Stream receiveBroadcastStream([ dynamic arguments])
dynamic arguments: 监听事件时向Native传递的数据。
初始化一个广播流用于从channel种接收数据,它返回一个Stream接下来要调用Stream的listen方法来完成注册,另外需要在也买你销毁的时候调用Stream的cancel方法来取消监听:
import 'package:flutter/services.dart';
...
static const EventChannel _eventChannelPlugin =
EventChannel('EventChannelPlugin');
StreamSubscription _streamSubscription;
@Override
void initState(){
_streamSubscription= _eventChannelPlugin
.receiveBroadcastStream()
.listen(__onToDart,onError: _onToDartError);
super.initState();
}
@Override
void dispose(){
if(_streamSubscription != null){
_streamSubscription .cancel();
_streamSubscription = null ;
}
super.dispose();
}
...
Native端:
//会构造一个StandardMethodCodec.INSTANCE类型的MethodCodec
EventChannel(BinaryMessenger messenger,String name)
//或者
EventChannel(BinaryMessenger messenger,String name,MethodCodec codec)
BinaryMessenger messenger: 消息的信使。
String name : channel的名字
MethodCodec codec : 用作MethodChannel的编解码器。
void setStreamHandler(EventChannel.StreamHandler handler)
EventChannel.StreamHandler handler:消息处理器,配置BinaryMessenger完成消息的处理:在创建好EventChannel后,如果要让其接收Dart发来的消息,则需要调用它的setStreamHandler方法为其设置一个消息处理器。
public interface StreamHandler{
void onListen(Object args,EventChannel.EventSink eventSink);
void onCancel(Object o);
}
void onListen(Object args,EventChannel.EventSink eventSink):FLutter Native监听事件时候调用,Obejct args是传递的参数,EventChannel.EventSink eventSink是Native回调Dart时的会回调函数,eventSink提供success、error、endOfStream回调方法分别对应事件的不同状态。
void onCancel(Object o): Flutter取消监听时调用。
public class EventChannelPlugin implements EventChannel.StreamHandler{
private List eventSinks = new ArrayList<>();
static EventChannelPlugin registerwith(FlutterView flutterView){
EventChannelPlugin plugin = new EventChannelPlugin();
new EventChannel(flutterView,"EventChannelPlugin").setStreamHandler(plugin);
return plugin;
}
void sendEvent(Object params){
for(EventChannel.EventSink eventSink : eventSinks){
eventSink .success(params);
}
}
@Override
public void onListen(Object args,EventChannel.EventSink eventSink){
eventSinks.add(eventSink);
}
@Override
public void onCancel(Obejct o){
}
}