Flutter & Native 混合开发

3,256 阅读4分钟

Flutter & Native 混合开发

项目集成方案

问题

  1. 项目中仍有大量业务使用 Native 开发。项目引入 Flutter 后,要求所有 Native 开发者都配置 Flutter 开发环境并改动项目工程结构,会对开发效率造成影响。
  2. 引入 Flutter 后,混合项目的构建流程会发生变动。打包环境需要配置 Flutter 开发环境,且 Native 项目无法单独构建。

需求

  1. 独立开发环境
  2. 独立构建

Flutter 项目模式

  1. Flutter 模式就是纯 Flutter 开发模式,原生项目被包在 Flutter 项目中,通过 Flutter 命令启动项目,命令会先编译 Flutter 工程,然后将 Flutter 编译产物复制到 Native 项目中,接着编译 Native ,最后启动 Native ,Native 调用 Flutter 。

  2. module 模式,Flutter 工程只负责产出 Flutter 编译产物,提供给 Native 工程使用。Flutter 和 Native 工程没有代码和环境依赖,Native 工程只依赖 Flutter 的编译产物。Flutter 工程和 Native 工程可以独立编译。

我们通过 flutter create 命令创建新的 Flutter 工程。这个命令有一个 --type 参数,通过传入 module 这个参数 , 命令会为我们创建一个 module 类型的 Flutter 项目。它和普通的 Flutter 项目只有些许不同,我们可以通过项目结构窥探一二。

从上面的图片可知,Flutter 项目模式和 module 模式在项目结构和文件上差不多,但在 iOS 和 Android 这两个和 Native 相关的文件夹上,Flutter 项目是直接将两个文件夹暴露出来,而 module 模式则是选择隐藏这两个 Native 文件夹。很显然,对于 Flutter 项目而言,Native 项目直接包在了 Flutter 项目中,必然需要在其中直接进行 Native 页面和逻辑的开发。而 module 模式中,,整个 Flutter 工程是和 Native 工程隔离开的,原则上不应该有 Native 的逻辑代码,因而隐藏了 Native 相关文件,不让用户有机会触碰或者添加 Native 代码。

既然 module 模式和 Native 项目完全隔离, 为什么还要保留一个隐藏的 Native 的项目呢?因为在 Native 平台上,Flutter 无法独立运行, 始终需要依附于一个 Native 项目才能够启动。因此为了在 module 模式下运行 App 进行调试,必定需要一个 Native App 的空壳来调起 Flutter 页面。

Native 调用 Flutter

要理解 module 模式如何工作,我们首先需要了解,一个纯 Flutter 工程是如何被 Native App 引用并调用的。

Flutter for iOS 的产物:

  1. App.framework:Dart 业务源码相关文件,以及项目依赖的静态资源,如字体,图片等
  2. Flutter.framework:Flutter 引擎库文件
  3. pubs 插件目录及用于索引的文件:Flutter 下的插件,包括各种系统的和自定义的channels

iOS Native 项目通过引入 Flutter.framework ,便可以调用 Flutter 项目中的代码,将 Flutter 嵌入到项目中。

Flutter for Android 的产物则是一个 flutter.aar,其中同样包含了 Flutter 引擎库以及项目中用到的静态资源等。Android 工程通过直接引入 flutter.aar ,便可以调用 Flutter 项目中的代码。

从上面的实践可知,只要我们取得了 Flutter for Native 的编译产物,便可以轻松的将 Flutter 工程嵌入到现有的 Native 项目中。其中,iOS 相对简单,直接将 Flutter 编译出的几个产物(Framwork、配置文件) 拖入 Native 项目中即可调用。安卓则需要修改 Native 工程中的 gradle,添加 aar 中的 Flutter 依赖。

Native 接入 Flutter 实践

目录结构如下

some/path/ flutter_host_android/ flutter_host_ios/ flutter_module/

保持 Native 和 Flutter 工程入口在同一目录下,三个工程各自由自己的 Git 进行版本管理。

flutter_module 目录下包含了 Flutter 开发人员编写的 Flutter 代码和 Flutter 的编译产物。对于 Native 工程而言,他们不关心其中的 Flutter 代码,他们只需要将资源定位到其中的编译产物,然后引入项目即可。

Android 引入 Flutter

在工程 settings.gradle 文件中添加

//增加内容

setBinding(new Binding([gradle: this]))

evaluate(new File( settingsDir.parentFile,'flutter_module/.android/include_flutter.groovy' ))

在工程 build.gradle 文件中添加

dependencies {
.
.
implementation project(':flutter')
}

当然配置完 gradle 后不要忘记同步。

需要注意的是,Flutter 开发人员在编写完代码提交到 Git 之前,需要执行一次完整的 Flutter 项目,以便生成最新的编译产物,否则 Native 端在调用 Flutter 时不会执行最新的代码。

当然,结偶性更好的方案是,只给 Native 开发人员提供 Flutter 产物,甚至使用 Cocoapods 这类包管理工具进行自动导入和版本控制。大家可以根据自己的需求来实现具体的工程配置。