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

news/2024/7/20 21:50:51 标签: flutter, android, ios

前言

在上篇中,我和大家分享了我对于Android原生与Flutter模块混合构建的一些经验,在本篇中,我将和大家分享Android原生和Flutter模块通信方面的经验。

所谓通信

事先声明,我这里所说的通信,指的就是Android原生和Flutter模块之间的方法互调,数据传递。
Flutter官方提供了Channel也即平台通道帮助开发者实现:

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

Flutter官方提供了三种Channel用于跨平台通信

你以为我要开始 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编译环境,AS的Terminal工具内直接输入下方命令

run_pigeon.sh

MacOS或Liunx编译环境,AS的Terminal工具内需要输入下方命令

./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生成的抽象方法,并返回对应的数据

作者:Randall_Xia
链接:https://juejin.cn/post/7192589048727207973


http://www.niftyadmin.cn/n/1458514.html

相关文章

解压缩编码列表

给你一个以行程长度编码压缩的整数列表 nums 。考虑每对相邻的两个元素 freq, val] [nums[2*i], nums[2*i1]] (其中 i > 0 ),每一对都表示解压后子列表中有 freq 个值为 val 的元素,你需要从左到右连接所有子列表以生成解压后…

Android进阶宝典 -- 告别繁琐的AIDL吧,手写IPC通信框架,5行代码实现进程间通信

对于进程间通信,很多项目中可能根本没有涉及到多进程,很多公司的app可能就一个主进程,但是对于进程间通信,我们也是必须要了解的。 如果在Android中想要实现进程间通信,有哪些方式呢? (1&…

抓住车载新风口,2023,让我们一飞冲天!

众所周知,我国是世界上最大汽车生产和销售国,汽车工业毫无疑问是我国经济发展的重要支柱。但随着移动互联网的发展,智能汽车也被推向了新的高度。 传统的车载已远远不能车主的需求,后装的主机厂商也无法提供相应的服务。为适应市…

整数的各位积和之差

给你一个整数 n,请你帮忙计算并返回该整数「各位数字之积」与「各位数字之和」的差。示例 1:输入:n 234 输出:15 解释: 各位数之积 2 * 3 * 4 24 各位数之和 2 3 4 9 结果 24 - 9 15 示例 2:输…

Flutter3.7版本新增组件-Menu菜单系列介绍

之前Flutter的菜单选择、下拉菜单的支持非常简单且不友好,对于非常常见的下拉菜单选择功能是需要自己自定义实现,今天看到Flutter3.7版本新增了一系列菜单的组件,马上来试试。 菜单组件介绍 本次Flutter稳定版本菜单系列组件新增了 MenuAnc…

送你一份 Android Jetpack 架构入门秘籍,从入门到强化实战

Jetpack 是一套库、工具和指南,可帮助开发者更轻松地编写优质应用。这些组件可帮助你遵循最佳做法、让你摆脱编写样板代码的工作并简化复杂任务,以便你将精力集中放在所需的代码上。而Compose则负责其余的工作-当状态发生改变时,你的UI将自动…

Android Studio Electric Eel 起支持手机投屏

当我们在线上做技术技术分享或者功能演示时,有时需要共享连接中的手机屏幕,通常我们会求助于 Vysor,Scrcpy 等工具。如果你是一个 Android Developer,那么现在有了更好的选择。 Android Studio 手机投屏 近期 Android Studio El…

二叉搜索树结点最小距离

给定一个二叉搜索树的根结点 root,返回树中任意两节点的差的最小值。示例:输入: root [4,2,6,1,3,null,null] 输出: 1 解释: 注意,root是树结点对象(TreeNode object),而不是数组。给定的树 [4,2,6,1,3,null,null] 可表示为下图:…