美文网首页Android
flutter 与原生Platform交互,开发插件包

flutter 与原生Platform交互,开发插件包

作者: 简单coder | 来源:发表于2021-12-26 14:58 被阅读0次

2021-12-27更新原生主动调用flutter

业务中的原生交互

由于目前我的测试需求只以 flutter为项目架构,所以本节只讲述flutter 主动调用原生,传递参数,接受原生参数返回.
直接上逻辑分析.原生主动调用 flutter 等需要各位自己去寻找其他文章.

Flutter提供三中原生和dart端的交互方式

  • BasicMessageChannel
  • MethodChannel
  • EventChannel
    BasicMessageChannel和MethodChannel底层实际都是在调用BinaryMessenger去发送消息,不过BasicMessageChannel发送的message 对象,MethodChannel发送的是MethodCall(method, arguments)对象,所以BasicMessageChannel发送的只是你的数据对象,MethodChannel发送的对象自带了 method和 argument,本质是没啥区别的


    至于EventChannel,则是使用了一个 streamcontroller 去接受BinaryMessenger的数据,这个看需求而采用.

所以这里我只MethodChannel做数据展示,BasicMessageChannel大同小异,其实用BasicMessageChannel也行,规则全部由你们自己确定,一级 command,二级 command 等等,只要做好 Map 中各类公共参数的区分即可.

flutter端

前端页面


class NativeTestPage extends StatefulWidget {
  const NativeTestPage({Key? key}) : super(key: key);

  @override
  _NativeTestPageState createState() => _NativeTestPageState();
}

class _NativeTestPageState extends State<NativeTestPage> {
  int _num = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("测试原生交互"),
      ),
      body: SafeArea(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextButton(
              child: Text("点击传递原生"),
              onPressed: () async {
                var res = await NativeChannel.to.getNum(_num);
                setState(() {
                  _num = res["num"] ?? 0;
                });
              },
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text("回传回来的文字 ${_num}"),
                SizedBox(
                  width: 10,
                ),
                // Text(
                //   controller.
                // ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

逻辑十分简单,点击按钮,调用原生获取 num,回显到底下的 label 上

NativeChannel

NativeChannel是我利用 GetService封装的一个单例,其内部逻辑也十分简单,封装了全局唯一通信通道com.taoqu.www.MethodChannel,所以的原生交互都通过该通道进行交互.

class NativeChannel extends GetxService {
  static NativeChannel get to => Get.find();

  final channel = MethodChannel('com.taoqu.www.MethodChannel');

  Future<Map<dynamic, dynamic>> getNum(int num) async {
    var result = await channel.invokeMethod('getNum', {'num': num});
    return result;
  }
}

invokeMethod

invokeMethod是通道与原生交互的方法,传入方法名,参数,这里建议与原生约定一个协议,所有参数都通过 Map 传递.


剩下的invokeListMethodinvokeMapMethod我觉得都没太必要使用的,我认为在实际的业务开发过程中,原生与 flutter 通信只要约定一个统一的协议,全都是用 map 传输即可.

iOS 端(Swift)

封装一个类MethodChannelDemo,参数的方法名,接受参数在下列代码中展示

public class MethodChannelDemo {
    init(messenger: FlutterBinaryMessenger) {
        let channel = FlutterMethodChannel(name: "com.taoqu.www.MethodChannel", binaryMessenger: messenger)
        channel.setMethodCallHandler { (call:FlutterMethodCall, result:@escaping FlutterResult) in
            if (call.method == "getNum") {
                if let dict = call.arguments as? Dictionary<String, Any> {
                    let num:Int = dict["num"] as? Int ?? 0
                    DispatchQueue.main.async {
                        //通过 result 回传数据
                        result(["num": num + 20])
                    }
                }
            }
        }
    }
}

调用逻辑在 application


  • iOS 端接受到 flutter 的参数详情


  • flutter 端接受到 iOS 端数据回传
    注意,回传的参数为Map<dynamic, dynamic>,而不是Map<String, dynamic>
    这里贴出出错的 exception
[VERBOSE-2:ui_dart_state.cc(209)] Unhandled Exception: type '_InternalLinkedHashMap<Object?, Object?>' is not a subtype of type 'Map<String, dynamic>' in type cast
#0      NativeChannel.getNum
package:flutter_dd/…/native_test/native_channel.dart:11

正确接受回传的参数为


Android 端(Kotlin)

毕竟我只是个做 iOS 的,Android 端我不太熟,稍微学了点空安全,做了下测试代码(Android 后面有需要再去看看),我们只需要知道 MethodCall类中 arguments 为接收参数,method 为方法命即可,
通过result.success来返回我们需要的数据

  • Android 注册flutter 方法响应类
class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        // 在 MainActivity中调用
        MethodChannelDemo(flutterEngine.dartExecutor.binaryMessenger)
    }
}
  • Android 接受到 flutter 参数代码
  • flutter 接收到 Android 回传的代码同 iOS.

顺便说一句,我好像在哪里看到网上的资料说是 flutter 不允许在非主线程调用 channel,我没有去验证这个结论,不过我验证了另外一个点,iOS 端是可以在非主线程调用数据回传的.



最后,展示下刚刚所写的双平台正常的通信.


2021-12-27更新原生调用 dart

iOS

我重新封装了下 iOS 端的消息处理类,主动发送消息也在里面

dart

flutter 中接收为



其实flutter 端和 platform 端的消息接收,发送代码调用方式都是一致的,这里可以点赞一下 flutter 的代码设计.

原生插件包开发

上面讲述的是对业务中各个平台的通信交互,而这里顺便讲一下对原生平台逻辑进行 plugin封装,以达到多项目能够使用同一插件的目的.
我们可以通过快捷创建项目的方式,创建出插件模板项目.
flutter create --org com.taoqu --template=plugin -a java -i swift --platforms=ios,android flutter_do_native

  • --org 为组织名称,体现在 ```Bundle Identifier
  • --template有4个参数
-t, --template=<type>        Specify the type of project to create.

          [app]              (default) Generate a Flutter application.
          [module]           Generate a project to add a Flutter module to an
                             existing Android or iOS application.
          [package]          Generate a shareable Flutter project containing
                             modular Dart code.
          [plugin]           Generate a shareable Flutter project containing an
                             API in Dart code with a platform-specific
                             implementation for Android, for iOS code, or for
                             both.
          [skeleton]         Generate a List View / Detail View Flutter
                             application that follows community best practices.

app为flutter 项目,module 为开发供原生调用的 framework,package 为纯 dart 三方,plugin 为各平台的三方.

  • --platforms=ios,android写法为左侧,可填入平台[ios (default), android (default), windows (default), linux (default), macos (default), web (default)]
  • -a java -i swift a 为安卓平台语言,i 为 iOS 平台语言
    这里我主要只提一点,打开项目后,需要在 example 例子中开发.iOS 平台的注册组件如下图位置.


    如果你在Development Pods中没有看到以你项目名称的文件夹,你得先用 flutter run 一下,如果有未指定平台的错误,说明你在创建项目中未填写--platforms=ios,android
    具体细节我就不说了,因为是在做通信中查询到的资料,这里就测试了一下创建逻辑,测试了下简单通信,为了以后的插件开发做准备.

更新不易,如有帮助到各位看官的,点个喜欢, 谢谢啦~

相关文章

网友评论

    本文标题:flutter 与原生Platform交互,开发插件包

    本文链接:https://www.haomeiwen.com/subject/dbnjqrtx.html