前言

在上篇中,我和咱们共享了我对于Android原生与Flutter模块混合构建的一些经历,在本篇中,我将和咱们共享Android原生和Flutter模块通讯方面的经历。

所谓通讯

事先声明,我这儿所说的通讯,指的便是Android原生和Flutter模块之间的办法互调,数据传递。 Flutter官方供给了Channel也即渠道通道协助开发者完成:

  • Flutter原生渠道发送音讯。
  • 原生渠道监听通道并接收音讯。然后,处理逻辑并将数据整合好之后作为响应发送回Flutter

Flutter官方供给了三种Channel用于跨渠道通讯

Channel 功能
MethodChannel 跨渠道办法互调
EventChannel 跨渠道音讯传递
BasicMessageChannel 跨渠道元数据传递

Android 原生混合 Flutter 开发初体验之二

你以为我要开始 1-2-3 开始给你介绍这三种Channel了吗?不!

官方文档在编写自定义的特定渠道代码一节中,以获取原生渠道电池电量为例演示了怎么运用MethodChannel进行跨渠道的办法调用,不难发现在MethodChannel的运用中,有两处(每个渠道)运用了硬编码字符串用于各渠道间的标识、匹配。这还只是调用了一个原生渠道的办法,实际生产中十个,百个办法都是有或许的!

鄙人非常讨厌这种涣散的无法管理的用于标识、匹配的硬编码字符串,由于团队中英文水平参差不齐,即便都很好,谁能确保自己不会手抖拼错呢,这就增加了一个或许的犯错点。因而,官网也在后半篇介绍了一种更安全的跨渠道通讯的办法。

Pigeon

Pigeon是一个用于Flutter原生渠道之间建立类型安全的通讯的代码生成东西,更快更易用。

Pigeon免去了在Flutter原生之间用硬编码字符串的办法匹配通道、音讯的名称和数据类型,并要求Flutter原生声明相同的参数和数据类型,生成以结构化类型安全办法发送音讯的代码。

其实,观察Pigeon生成的代码可以发现,Pigeon其实也是凭借BasicMessageChannel完成通讯的,只不过它以脚本的办法生成了模板代码,正是在这个过程中避免了手写硬编码或许出现的问题。

Pigeon的运用

增加Pigeon依赖

dart pub add pigeon

然后

dart pub get

创立pigeon文件夹并新建一个platformApi.dart文件用于声明对应的办法

这儿platformApi.dart的文件命名可自定义

pigeon/platformApi.dart

import 'package:pigeon/pigeon.dart';
// 这是声明 Flutter 调用原生办法
// 如果是原生调用 Flutter 办法,请运用 @FlutterApi() 注解
@HostApi()
abstract class AndroidBatteryApi {
  int getAndroidBattery();
}

新建Pigeon脚本用于生成对应的通讯代码

复制下方代码创立一个run_pigeon.sh文件,将下方代码复制,针对你的项目修改成对应的文件名,文件路径

$ flutter pub run pigeon \

  --input pigeon/platformApi.dart \
  --dart_out lib/api_generated.dart \
  --experimental_kotlin_out android/app/src/main/kotlin/com/randalldev/native_provider/Pigeon.kt \
  --experimental_kotlin_package "com.randalldev.native_provider"

我这儿只生成了Android渠道的模板代码

pigeon东西还有其他指令选项,比方iOS渠道

  --objc_header_out ios/Runner/pigeon.h \
  --objc_source_out ios/Runner/pigeon.m \
  --experimental_swift_out ios/Runner/Pigeon.swift \

执行脚本,会生成各端需求的原生代码

Windows编译环境ASTerminal东西内直接输入下方指令

run_pigeon.sh

MacOSLiunx编译环境,ASTerminal东西内需求输入下方指令

./run_pigeon.sh

完成原生办法的逻辑

pigeon脚本生成代码是接口类,咱们需求完成接口,并完成其内部的办法

翻开android/app/src/main/kotlin/com/randalldev/native_provider/MainActivity.kt

运用延迟加载的办法新建一个实例,这是一种更安全更方便的写法,根据需求的参数挑选内部类的办法有时也可以,关注内部完成即可

    private val batteryApi by lazy {
        object : AndroidBatteryApi {
            override fun getAndroidBatteryApi(): Long {
                TODO("Not yet implemented")
            }
        }
    }

TODO部分便是咱们需求完成的Android渠道的逻辑

针对需求异步操作才能获取回来值的状况

这种状况通常出现在一些网络操作、文件操作的状况。

声明异步的办法

还是之前的platformApi.dart文件,增加一个异步办法的声明

  
  @async
  int getAsyncAndroidBattery();
  

运转run_pigeon.sh脚本,生成新声明的办法,并在Android渠道增加完成

    private val batteryApi by lazy {
        
            override fun getAsyncAndroidBattery(callback: (Long) -> Unit) {
                TODO("Not yet implemented")
            }
        
    }

完成异步逻辑

    private val batteryApi by lazy {
        
            override fun getAsyncAndroidBattery(callback: (Long) -> Unit) {
                // 演示代码,实际没有这样的 api
                system.getBattery(object : BatteryResultListener {
                        override fun onSucceed(battery: Integer) {
                            callback.invoke(battery)
                        }
                        override fun onFailed(msg: String?) {
                            callback.invoke(-1)
                        }
                    })
            }
        
    }

总结

Flutter供给了Channel用于完成与原生渠道的通讯,可是基于我个人的技术挑选,我挑选了运用官方供给的代码生成东西Pigeon去生成ChannelApi 的代码。

运用Pigeon主要是以下这几个步骤

  • 增加依赖
  • 创立pigeon相关dart文件并声明需求的办法
  • 编写并运转pigeon脚本
  • 原生渠道完成Pigeon生成的抽象办法,并回来对应的数据

参阅文章

Writing custom platform-specific code

[Flutter] 运用 Pigeon 完成跨渠道办法调用

Pigeon