通信原理
我们分几种场景来介绍Flutter和Native之间的通信。
- Native发送数据给Flutter
- Flutter发送数据给Native
- Flutter发送数据给Native,然后Native回传数据给Flutter
Flutter与Native通信机制
在讲解Flutter与Native之间是如何传递数据之前,我们先了解下Flutter与Native的通信机制,Flutter和Native的通信是通过Channel来完成的。
消息使用Channel(平台通道)在客户端(UI)和主机(平台)之间传递,如下图所示:
- Channel所支持的数据类型对照表
- Flutter定义了三种不同类型的Channel:
- BasicMessageChannel:用于传递字符串和半结构化的信息,持续通信,收到消息后可以回复此次消息,如:Native将遍历到的文件信息陆续传递到Flutter,在比如:Flutter将从服务端陆陆续续获取到信息交给Native加工,Native处理完返回等;
- MessageChannel:用于传递方法调用,一次性通信:如Flutter调用Native拍照;
- EventChannel:用于数据流的通信,持续通信,通常用于Native向Flutter的通信,如:手机电量变化,网络连接变化等;
这三种类型的Channel都是全双工通信,即A<=>B,Flutter可以主动发送消息给Native端,并且Native接收到消息后可以做出回应,同样,Native端可以主动发送消息给Flutter端,Flutter端接收到数据后返回给Native。
通信原理
- 无论是哪一种类型的Channel,它能和Flutter进行通信主要是借助BinaryMessenger来实现的。
- 三种类型的Channel在Flutter侧都有对应的实现。
实践
- flutter主动发送数据给native,native接受到消息后回信给flutter
- Android端
class MainActivity : FlutterActivity() {override fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)val channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "HiFlutterBridge")//HiFlutterBridge需要和flutter端的对应channel.setMethodCallHandler { call, result ->Log.e("HiFlutterBridge", "argus is ${call.arguments}")if (call.method == "goToNative") {val data = "Hello from native!"result.success(data)} else {result.notImplemented()}}}
- Flutter端
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';class HiFlutterBridge {static HiFlutterBridge _instance = HiFlutterBridge._();final MethodChannel _bridge = const MethodChannel("HiFlutterBridge");//需要和原生端的MethodChannel方法的第二个参数一致var _listener = {};HiFlutterBridge._() {_bridge.setMethodCallHandler((MethodCall call) {String method = call.method;if (_listener[method] != null) {return _listener[method](call);}return Future(() => null);});}static HiFlutterBridge getInstance() {return _instance;}register(String method, Function(MethodCall) callBack) {_listener[method] = callBack;}unRegister(String method) {_listener.remove(method);}goToNative(Map params) async {String result = await _bridge.invokeMethod("goToNative", params);debugPrint("HiFlutterBridge result is $result");}MethodChannel bridge() {return _bridge;}
}
Widget build(BuildContext context) {// TODO: implement buildreturn Scaffold(resizeToAvoidBottomInset: false, // 设置为false以避免在打开软键盘时widget被顶上去body: HideKeyboard(child: Stack(children: <Widget>[Align(alignment: Alignment.center,child: ElevatedButton(onPressed: () => {//flutter向native端通信HiFlutterBridge.getInstance().goToNative({"test": "hello world"})},// style: ElevatedButton.styleFrom(// minimumSize: const Size(100, 50),// maximumSize: const Size(100, 50),// shape:// RoundedRectangleBorder(borderRadius: BorderRadius.circular(30))),child: const Text('login'),),)],)));}
- native主动发送数据给flutter,flutter接受到消息后回信给native
- Android端
class MainActivity : FlutterActivity() {override fun onResume() {super.onResume()sendDataToFlutter()}private fun sendDataToFlutter() {val channel = MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, "test")channel.invokeMethod(" sendData ", "Hello Flutter", object : MethodChannel.Result {override fun success(o: Any?) {Log.d("Native", "Received back: " + o.toString())}override fun error(s: String, s1: String?, o: Any?) {Log.e("Native", "Error: $s1")}override fun notImplemented() {}})}
}
- Flutter端
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';class HiFlutterBridge {static HiFlutterBridge _instance = HiFlutterBridge._();final MethodChannel _bridge = const MethodChannel("test");var _listener = {};HiFlutterBridge._() {_bridge.setMethodCallHandler((MethodCall call) async{debugPrint("test ===> ${call}");return "flutter ===> native";String method = call.method;if (_listener[method] != null) {return _listener[method](call);}return Future(() => null);});}static HiFlutterBridge getInstance() {return _instance;}register(String method, Function(MethodCall) callBack) {_listener[method] = callBack;}unRegister(String method) {_listener.remove(method);}goToNative(Map params) async {String result = await _bridge.invokeMethod("goToNative", params);debugPrint("HiFlutterBridge result is $result");}MethodChannel bridge() {return _bridge;}
}
void initState() {// TODO: implement initStatesuper.initState();HiFlutterBridge.getInstance();}
- 运行结果
I/flutter (27181): test ===> MethodCall( sendData , Hello Flutter)
D/Native (27181): Received back: flutter ===> native