Flutter: Flutter与Native通信

Flutter与Native的通信场景:

1.Flutter Module < ---- init Params ----Native Module

2.Flutter Module <---- ---- Native Module

3.Flutter Module ----  > Native Module

4.Flutter Module < ----  > Native Module


Flutter与Native通信机制:MethodChannel.

所谓“平台特定”或“特定平台”,平台指的就是指Flutter运行的平台,如Android或IOS,可以认为就是应用的原生部分。所以,平台通道正是Flutter和原生之间通信的桥梁,它也是Flutter插件的底层基础设施。

Flutter使用了一个灵活的系统,允许您调用特定平台的API,无论在Android上的Java或Kotlin代码中,还是iOS上的ObjectiveC或Swift代码中均可用。

Flutter与原生之间的通信依赖灵活的消息传递方式:

  • 应用的Flutter部分通过平台通道(platform channel)将消息发送到其应用程序的所在的宿主(iOS或Android)应用(原生应用)。
  • 宿主监听平台通道,并接收该消息。然后它会调用该平台的API,并将响应发送回客户端,即应用程序的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

Flutter中定义的3种不同的Channel:

 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端。

BasicMessageChannel:

Dart端:

//构造方法原型:
const BasicMessageChannel(this.name,this.codec);

String name : Channel 的名字,要和Native端保持一致。

MessageCodec codec : 消息的编解码器,要和Native保持一致。有4种类型的实现具体可以参考Native端的介绍。

Dart端到platform传递的过程种是以2进制的形式传递的,比如发送String类型数据,Dart通过编解码器将数据变成2进制,在Android端通过这个编解码器解码为String,Android端才能进行使用。

 

//setMessageHandler方法的原型
void setMessageHandler(Future handler(T message))

Flutter handler(T message) :消息处理器,配合BinaryMessenger完成消息的处理。

Dart端:在创建好BasicMessageChannel后,如果要让其接收Native发送来的消息,则需要调用它的setMessageHandler方法为其设置一个消息处理器。

 

//send方法原型
Future send(T message)

T message: 要传递给Native的具体信息。

Future: 消息发出去后,收到Native回复的回调函数。

在创建好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 codec: 消息的编解码器,4种不同的类型的实现:

    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 var2) : 用于接收消息,var1是消息内容,var2是回复此消息的回调函数。

 

void send(T message)
void send(T message ,BasicMessageChannel.Reply callback)

T message: 要传递给Dart的具体信息。

BasicMessageChannel.Reply  : 消息发出去后,收到Dart的回复的回调函数。

在创建好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){
    
    }
        
}  

 

 

MethodChannel:

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();
}

}

 

EventChannel:

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){
    
    }
}

 

你可能感兴趣的:(Flutter)