Flutter完整开发实战详解(十4、混合开发打包 Android 篇)

本篇将带你深刻了解 Flutter 中打包和插件安装等原理,帮你快速完成 Flutter 集成到现有 Android 项目,实现混合开发支持。java

前文:react

1、前言

随着各类跨平台框架的不断涌现,不少时候咱们会选择混合开发模式做为脚手架 ,由于企业通常不会把业务都压在一个框架上,同时除非是全新项目,否则出于对原有业务重构的 成本和风险 考虑,都会选择混合开发去尝试入坑。android

可是混合开发会对 打包、构建和启动等流程熟悉度要求较高 ,同时遇到的问题也更多,之前我在 React Native 也写过相似的文章 :《从Android到React Native开发(4、打包流程解析和发布为Maven库)》 ,而这方面是有不少经验能够通用的,因此适当的混开模式有利于避免一些问题,同时只有了解 Flutter 总体项目的构建思路,才有可能更温馨的躺坑。git

额外唠叨一句,跨平台的意义更多在于解决多端逻辑的统一 ,至少避免了逻辑重复实现,因此企业刚开始,通常会选择一些轻量级业务进行尝试。github

官方将来将有 Flutter build aar 的方法可提供使用。

2、打包

通常跨平台混合开发会有两种选择:web

  • 一、将 Flutter 总体框架依赖和打包脚本都集成到主项目中。
  • 二、以 aar 的完整库集成形式添加到主项目。

两种实现方法各有利弊:npm

  • 第一种方式能够更方便运行时修改问题,可是对主项目“污染”会比较高,同时改动会大一些。react-native

  • 第二种方式 须要单独调试后,更新 aar 文件再集成到项目中调试,可是这类集成方式更干净,同时 Flutter 相关代码可独立运行测试,且改动较小。缓存

通常而言,对于普通项目我是建议以 第二种方式集成到项目中的 ,经过新建一个 Flutter 工程,而后对工程进行组件化脚本处理,让它 既能以 apk形式单独运行调试,又能打包为aar形式对外提供支持。app

相信对于原平生台熟悉的应该知道,咱们能够经过简单修改项目gradle 脚本,让它快速支持这个能力,以下图片所示,图片中为省略的部分脚本代码,完整版可见 flutter_app_lib

咱们经过了 isLib 标记为去简单实现了项目的打包判断,当项目做为 lib 发布时,设置 isLib 为 true,以后执行 ./gradlew assembleRelease 便可 ,剩下的工做依旧是 Flutter 自身的打包流程,而对于打包后的 aar 文件直接在原生项目里引入便可完成依赖。

而通常接入时,若是须要 token 、用户数据等信息,推荐提供定义好原生接口,如 init(String token, String userInfo) 等,而后经过MethodChannel 将信息同步到 Flutter 中。

对于原生主工程,只须要接入 aar 文件,完成初始化并打开页面,而无需关心其内部实现,和引入普通依赖并没有区别。

你可能须要修改的还有 AndroidManifset 中的启动 MainActivity 移除,而后添加一个自定义 Activity 去继承 FlutterActivity 完成自定义。

3、插件

若是普通状况下,到上面就能够完成 Flutter 的集成工做了,可是每每事与愿违,一些 Flutter 插件在提供功能时,每每是经过原生层代码实现的,如 flutter_webviewandroid_intentdevice_info 等等,那这些代码是怎么被引用的呢?

这里稍微提一下,用过 React Native 的应该知道,带有原生代码的 React Native 插件,在 npm 安装之后,须要经过 react-native link命令完成安装处理。 这个命令会触发脚本修改原生代码,从而修改 gradle 脚本增长对插件项目的引用,同时修改 java 代码实现插件的模版引入,这使得项目在必定程度被插件“污染”。

React Native 中带有原生代码的插件,会被以本地 Module 工程的方式引入,那 Flutter 呢?

其实原理上 Flutter 带有原生代码的插件,在插件安装后,也是会以本地 Module Project 的形式引入 ,可是它整个过程更加巧妙,让开发中对这个过程几乎无感。

以下图所示,不知道你注意过没有,在插件安装以后,全部带原生代码的插件,都会以路径和插件名的key=value 形式 存在 .flutter-plugins 文件中。

而在 android 工程的 settings.gradle 里,以下图所示,会经过读取该文件将 .flutter-plugins 文件中的项目一个个 include 到主工程里。

以后就是主工程里的 apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 脚本的引入了,这个脚本通常在于 flutterSDK/packages/flutter_tools/gradle/ 目录下,以下代码所示,其中最关键的部分一样是 读取 .flutter-plugins 文件中的项目,而后一个一个再 implementation 到主工程里完成依赖。

自此全部原生代码的 Flutter 插件,都被做为本地 Module Project 的形式引入主工程了 ,最后脚本会自动生成一个 GeneratedPluginRegistrant.java 文件,实现原生代码的引用注册, 而这个过程对你彻底是无感的。

说了那么多就是为了说明,既然插件是被看成本地 Module Project 的形式引入,那么这时候按照原来直接打包 aar 是会有问题的:

`Android` 默认 `gradle` 脚本打包时,对于 `project` 和远程依赖只会打包引用而不会打包源码和资源。

因此这时候就须要 fat-aar 的加持了,关于 fat-aar 的详细概念可见 :《从Android到React Native开发(4、打包流程解析和发布为Maven库)》 ,这里能够简单理解为,这是一个支持将引用代码和资源到合并到一个 aar 的插件。

以下代码所示,咱们在本来的组件化脚本上,经过增长 apply plugin: 'com.kezong.fat-aar' 引入插件,而后参考 Flutter 脚本对 .flutter-plugins 文件中的项目进行 embed 依赖引用便可 ,这时候再打包出的 aar 文件即为完整 Flutter 项目代码。

完整版可见 flutter_app_lib

4、堆栈

最后须要说的问题就是堆栈了。

若是说混合开发中最难处理的是什么,那必定是各平台之间的堆栈管理,通常状况下咱们都会避免混合堆栈的相互调用 ,可是面对不得不如此为之的状况下,闲鱼给出了他们的答案:fluttet_boost

咱们知道 Flutter 整个项目都是绘制在一个 Surface 画布上,而fluttet_boost 将堆栈统一到了原生层,经过一个单例的 flutter engine 进行绘制。

每一个 FlutterFragmentFlutterActivity 都是一个 Surface承载容器,切换页面时就是切换 Surface 渲染显示,而对于不渲染的页面经过 Surface 截图缓存画面显示。

这样整个 Flutter 的路由就被映射到原生堆栈中,统一由原生页面堆栈管理,Flutter 内每 push 一个页面就是打开一个 Activity

flutter_boost 截止到我测试的时间 2019-05-16, 只支持 1.2以前的版本。 flutter_boost 的总体流程相对复杂,同时对于 Dialog 的支持并很差,且业务跳转深度太深时会出现黑屏问题。

自此,第十四篇终于结束了!(///▽///)

资源推荐

完整开源项目推荐:

咱们还会再见吗?
相关文章
相关标签/搜索