Flutter 混合开发基础

2023-06-03 0 509

结语

Flutter 做为 Google 开放源码的第三代虚拟化、高效能 UI 架构,旨在帮助合作开发人员高效率地构筑出虚拟化的、UI 与可视化新体验一致的精致应用领域,面世后一直备受合作开发人员的青睐。

当须要合作开发两个崭新的应用领域时,我们可以很方便地从头开始,完全采用 Flutter 展开合作开发。但如果是针对两个原有的应用领域,须要导入 Flutter 控制技术,显然采用 Flutter 全部改写一遍是不现实的。幸运地的是,Flutter 较好地全力支持了以分立网页、甚至是 UI 短片的形式软件系统到原有的应用领域中,即所谓的混和合作开发商业模式。责任编辑主要就从两个 Android 合作开发的视点,聊聊 Android 网络平台下, Flutter 的混和合作开发与构筑。

Hello Flutter

相信现在如果很少会有终端端合作开发人员不知道 Flutter,这里不再做过多介绍。对于尖萼控制技术,采用过的如果绝大多数单厢该死;喷过的推荐尝试呵呵,跑个 Demo 新体验新体验,有可能它就是你须要学习和掌握的最后两门新控制技术了。再来,Flutter 究竟有什么独特的气质让它能从众位控制技术中十强呢?总结呵呵,主要就有几点:

虚拟化:可以做到一套标识符轻松网络连接 Android、iOS 网络平台,未来还会覆盖更多网络平台,大大节约了合作开发物力与维护成本,同时拥有出众的跨端 UI 表现连续性。高效率合作开发:SDK 提供更多了丰富的 UI 组件,照相狸尾豆;声明式的 UI 构筑形式,大大增加普遍化;Debug 商业模式提供更多热空载潜能,可动态自动更新标识符变更,不须要重新校对加装。高效能:采用自建图形发动机,分立于控制系统并可单独优化;区别于 RN、WEEX,没有第二层转换的附加开支;Release 商业模式下标识符校对为 AOT 命令,运行高效率。

受益于以上的核心优势,Flutter 面世后圈了很多终端合作开发人员的粉,各互联网小厂也纷纷将其做为一项此基础控制技术展开研究。在 Flutter 初期,其应用领域情景主要就是从 0 构筑两个崭新 App,对混和合作开发的全力支持很不亲善。但做为两门虚拟化的控制技术架构,到底还是须要依赖原生植物网络平台提供更多的诸多控制系统潜能,此外还有众多现存原生植物 App 摩拳擦掌,因此在这个需求背景下,混和合作开发的全力支持与完善至今已发展得越来越好,下面我们就用两个简单的实例开始 Android 端 Flutter 混和合作开发与构筑之旅。

导入 Flutter 组件

要在两个已有的 Android Project 中采用 Flutter,须要导入两个 Flutter Module。在 Android Studio(须要确保 Flutter 应用程序已经成功加装并投入使用)中打开原有 Android 工程,通过采用 File > New > New Module… 菜单,我们可以新创建两个 Flutter 组件或是导入两个外部的 Flutter 组件。

Flutter 混合开发基础

这里以最简单的 Android App 项目为例,导入 Flutter 组件。在 Flutter 组件导入成功之后,原工程文件、结构单厢发生一些变化,主要就有:

settings.gradle 文件新增了以下内容。其实就是执行对应 Flutter 组件下 .android/include_flutter.groovy 脚责任编辑件,该步骤会导入两个名为 Flutter 的 Android Library Module,同时还会导入 Flutter 组件所依赖的所有应用程序。setBinding(new Binding([gradle: this])) evaluate(new File(   settingsDir.parentFile,   flutter_module/.android/include_flutter.groovy )) include :flutter_module project(:flutter_module).projectDir = new File(../flutter_module)项目结构变化,如下图所示:
Flutter 混合开发基础

在导入 Flutter 组件之前,项目中仅有 app 两个 Module;而在导入之后,可以看到除了原有的 app Module 外,Flutter Gradle 应用程序自动导入了附加几个子 Module:

flutter_module:指代要导入的目标 Flutter Module,不会 apply Android 相关的任何应用程序,主要就是包含 Flutter 相关源码、资源、依赖等。flutter:为 Flutter Gradle 应用程序导入的 Android Library Module;主要就负责校对 flutter_module 及其依赖的第三方 Package、Plugin 的 Dart 标识符,以及打包 Flutter 资源等。device_info:为 Flutter Gradle 应用程序自动导入的 Flutter Android Plugin Library Module,这是因为一开始我在 flutter_module 的 pubspec.yaml 文件中添加了对 device_info 这个应用程序的依赖。Flutter Gradle 工具会将 flutter_module 依赖到的所有应用程序其 Android 网络平台侧的标识符、资源做为两个 Library Module 导入到项目中一起参与构筑。如果要查看 flutter_module 导入了哪些 Plugin,可以查看其对应目录下的 .flutter-plugins 与 .flutter-plugins-dependencies 文件,这两个文件是执行 flutter pub get 时生成的,记录了应用程序的本地文件目录、依赖信息等。

注意:两个工程不能包含多个 Flutter Module,最多只能导入两个,这是由 Flutter 的 Gradle 应用程序决定的。

使用 Flutter

完成 Flutter 组件的导入后,我们再来看看如何采用 Flutter。

添加依赖

首先须要在 App 组件的build.gradle脚责任编辑件中添加对Flutter工程的依赖,只有这样 Flutter 组件才会参与到整个应用领域的构筑中来,我们也才能够在 App 组件中调用到 Flutter 提供更多的 Java 层 API。如下所示:

dependencies { implementation project(:flutter) }

运行 Flutter 网页

我们可以选择采用 Activity、Fragment 或者 View 来承载 Flutter 的 UI,这里主要就介绍前面两种形式,并假设flutter_module中已经通过runApp方法图形了两个widget。

运行 Flutter Activity。采用io.flutter.embedding.android.FlutterActivity类可以很方便的启动两个 Flutter Activity,当然我们也可以继承它并扩展自己的逻辑。实例标识符如下:FlutterActivity .withNewEngine() .build(context) .also { startActivity(it) }运行 Flutter Fragment。可以采用FlutterFragmentActivity或者FlutterFragment来添加 Flutter UI 短片:a. 采用FlutterFragmentActivity可以自动创建并添加两个FlutterFragment;b. 手动创建FlutterFragment后添加到目标 Activity 中。实例标识符如下:val flutterFragment = FlutterFragment.withNewEngine() .dartEntrypoint(getDartEntrypointFunctionName())   .initialRoute(getInitialRoute())   .appBundlePath(getAppBundlePath()) .flutterShellArgs(FlutterShellArgs.fromIntent(intent))   .handleDeeplinking(shouldHandleDeeplinking()) .renderMode(renderMode)   .transparencyMode(transparencyMode) .shouldAttachEngineToActivity(shouldAttachEngineToActivity())   .build<FlutterFragment>() fragmentManager   .beginTransaction()   .add(         FRAGMENT_CONTAINER_ID, flutterFragment,         TAG_FLUTTER_FRAGMENT       )     .commit()网络平台层和 Flutter 层通信。不论是合作开发 Plugin 还是业务逻辑,网络平台层与 Flutter 层通信是必不可少的,为此就须要采用到MethodChannel。网络平台层通过MethodChannel请求调用 Flutter 层 API 时,数据在经过打包编码后,通过 JNI、DartVM 传到 Flutter 层解码后采用;待结果计算完成后,又会重新打包编码,经过 DartVM、JNI 传回到 Native 层;同理,在 Flutter 层请求调用网络平台层的 API 时,数据处理是一致的,只是流转方向相反。通过这种形式,网络平台层与 Flutter 层就建立了两个双向的、异步的通信通道。在下面的实例标识符中,Native 层采用dev.flutter.example/counter创建两个MethodChannel,并设置 Handler 接收 Dart 的远程方法调用 incrementCounter,并调用 reportCounter 将结果回传。channel = MethodChannel(flutterEngine.dartExecutor,“dev.flutter.example/counter”) channel.setMethodCallHandler { call, _ ->     when (call.method) {“incrementCounter”-> {             count++             channel.invokeMethod(“reportCounter”, count)         }     } }

Dart 层采用相同的名称创建 MethodChannel,并设置 Handler 处理回调结果,随后调用 incrementCounter 方法请求 counter。实例标识符如下:

final _channel = MethodChannel(dev.flutter.example/counter); _channel.setMethodCallHandler(_handleMessage); _channel.invokeMethod(incrementCounter); Future<dynamic> _handleMessage(MethodCall call) async {   if (call.method == reportCounter) {     _count = call.argumentsas int;     notifyListeners();   } }

这里我们是通过手动创建 MethodChannel 展开通信的,这在展开简单通信的情景是没问题的,但在通信接口 API 比较复杂的情况就不是很适用了。

一是繁琐,因为我们须要手写大量的打包、拆包标识符;二是容易出错。这个时候就轮到 Pigeon 大显身手了。Pigeon 是两个官方面世的标识符生成工具,可以生成类型安全的双向通信 API 接口,具体可以参考官方的 Example,这里不再赘述。

Pigeon :https://flutter.dev/docs/development/platform-integration/platform-channels#pigeon

Flutter APK 解析

到这里,我们已经了解了如何在原有 Android 项目中导入并采用 Flutter,接下来我们再来探究呵呵 Flutter APK 的结构,看看 Flutter Tools 在这个 APK 包内到底打包了哪些东西。下面两图分别为 Debub 商业模式和 Release 商业模式下构筑出来的 Flutter APK 包结构,忽略了非 Flutter 相关的项。

Flutter 混合开发基础

可以看到两个商业模式下的 APK 结构大致相同,说明如下:

lib/{arch}/libflutter.so:为对应架构的 Flutter Engine 共享库,负责 Flutter 图形、JNI 通信、DartVM。如果不须要对应架构的版本,通过 abiFilters 可以 Exclude 掉。lib/{arch}/libapp.so:只存在于 Release 商业模式下,共享库中包含 Dart AOT 生成的二进制命令和数据。在运行时,Flutter Engine 通过 Dynamic Load 的方式,从共享库中读取对应的可执行机器命令以及数据。assets/flutter_assets:Flutter 引用到的相关资源 fonts:包含字体库。FontManifest.json:引用到的字体库清单文件,json 格式,所有采用到的字体、以及字体文件在 flutter_assets 下的路径。AssetManifest.json:其他资源清单文件,json 格式,为所有资源名称到资源路径的映射,Flutter 在加载某一项资源时,会通过这个配置清单找到对应路径的资源展开读取后加载。kernel_blob.bin、isolate_snapshot_data、vm_snapshot_data:只存在于 Debug 商业模式下,分别为 DartVM 字节码与数据,其作用类似于 libapp.so,只是存在形式、打包形式不同。在 Debug 商业模式下,Flutter Tools 将命令和数据分别打包,主要就是为了热空载(HotReload)服务的,而在 Release 商业模式下是统一打包成共享库。

踩过的坑

这里,也总结了几个我们在应用领域的时候遇到的问题,供大家参考避坑。

路由管理复杂:这里面包括 Flutter 层内部的网页路由管理以及 Flutter 与原生植物的混和栈管理。前者在 Navigator 2.0 API 中已经得到了较好的完善与全力支持,但后者仍面临着诸多限制与不足,须要改进。目前项目中还未涉及到后者这种很复杂的业务情景,因此对这一块的研究比较少,感兴趣的同学可以了解呵呵诸如 flutter_boost 此类的开放源码解决方案。生命周期不对应:Android 的组件一般单厢有自己的生命周期,Flutter 的 Widget State 也有一套自己的生命周期,但这两者其实并不是一一对应的。比如原生植物的 Activity 网页虽然已经被 Finish 并 Destroy 掉了,但 Flutter 层的网页并不一定会随之而被 Dispose,尤其是在采用 Cache Flutter Engine 的时候。Flutter 网页是可以脱离原生植物网页而存在的,它们可以被动态地 Attach 和 Detach,Attach 时会触发重新图形,Detach 时 UI 相关的所有操作单厢 Pending 直到重新被 Attach。所以在混和合作开发中,业务逻辑不如果过度依赖 Widget State 的一些生命周期方法,因为它们可能会被延后执行从而导致一些奇怪的 Bug。

总结

Flutter 混和合作开发使得合作开发人员可以渐进式地展开 Flutter 合作开发与迁移,是 Flutter 寄生于原生植物网络平台至关重要的一环。

责任编辑主要就从两个 Android 合作开发的视点,介绍了 Flutter 混和合作开发的入门知识。随着 Flutter 开放源码项目的不断迭代与演进,混和合作开发的新体验正在变得越来越好、性能也越来越高。但美中不足的

瑕不掩瑜,Flutter 尖萼控制技术整体而言还是非常不错的,它如今仍处于快速发展的阶段,相信在 Flutter 团队与开放源码社区的共同努力下,未来的生态值得期待。

作者简介

李成达,网易云信资深终端端合作开发工程师,热衷于研究虚拟化合作开发控制技术以及工程提效,目前主要就负责视频会议组件化 SDK 的相关研发工作。

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务