Flutter与Native通信原理剖析与实践

通信原理

我们分几种场景来介绍Flutter和Native之间的通信。

  • Native发送数据给Flutter
  • Flutter发送数据给Native
  • Flutter发送数据给Native,然后Native回传数据给Flutter

Flutter与Native通信机制

在讲解Flutter与Native之间是如何传递数据之前,我们先了解下Flutter与Native的通信机制,Flutter和Native的通信是通过Channel来完成的。

消息使用Channel(平台通道)在客户端(UI)和主机(平台)之间传递 ,如下图所示:

  • Channel所支持的数据类型对照表
  • Flutter定义了三种不同类型的Channel:
    1. BasicMessageChannel:用于传递字符串和半结构化的信息,持续通信,收到消息后可以回复此次消息,如:Native将遍历到的文件信息陆续传递到Flutter,在比如:Flutter将从服务端陆陆续续获取到信息交给Native加工,Native处理完返回等;
    2. MessageChannel:用于传递方法调用,一次性通信:如Flutter调用Native拍照;
    3. EventChannel:用于数据流的通信,持续通信,通常用于Native向Flutter的通信,如:手机电量变化,网络连接变化等;

这三种类型的Channel都是全双工通信,即A<=>B,Flutter可以主动发送消息给Native端,并且Native接收到消息后可以做出回应,同样,Native端可以主动发送消息给Flutter端,Flutter端接收到数据后返回给Native。

通信原理

  • 无论是哪一种类型的Channel,它能和Flutter进行通信主要是借助BinaryMessenger来实现的。
  • 三种类型的Channel在Flutter侧都有对应的实现。

实践

  • flutter主动发送数据给native,native接受到消息后回信给flutter
    1. Android端
dart 复制代码
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()
            }
        }
    }
  1. Flutter端
dart 复制代码
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;
  }
}
dart 复制代码
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return 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
    1. Android端
dart 复制代码
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() {}
        })
    }
}
  1. Flutter端
dart 复制代码
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;
  }
}
dart 复制代码
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    HiFlutterBridge.getInstance();
  }
  • 运行结果
dart 复制代码
I/flutter (27181): test ===> MethodCall( sendData , Hello Flutter)
D/Native  (27181): Received back: flutter ===> native
相关推荐
花花鱼2 小时前
android studio 设置让开发更加的方便,比如可以查看变量的类型,参数的名称等等
android·ide·android studio
alexhilton3 小时前
为什么你的App总是忘记所有事情
android·kotlin·android jetpack
小蜜蜂嗡嗡7 小时前
flutter封装vlcplayer的控制器
前端·javascript·flutter
AirDroid_cn7 小时前
OPPO手机怎样被其他手机远程控制?两台OPPO手机如何相互远程控制?
android·windows·ios·智能手机·iphone·远程工作·远程控制
尊治7 小时前
手机电工仿真软件更新了
android
xiangzhihong810 小时前
使用Universal Links与Android App Links实现网页无缝跳转至应用
android·ios
车载应用猿10 小时前
基于Android14的CarService 启动流程分析
android
没有了遇见11 小时前
Android 渐变色实现总结
android
雨白14 小时前
Jetpack系列(四):精通WorkManager,让后台任务不再失控
android·android jetpack
mmoyula15 小时前
【RK3568 驱动开发:实现一个最基础的网络设备】
android·linux·驱动开发