浅谈 Flutter 的 Android 混合开发

本篇文章为公司内部分享时所写，基于的 flutter 版本也已过时，所以可能有不对的地方，还请指出。现在放到博客上，以后有机会再完善。

前言

Flutter 是谷歌的移动 UI 框架，可以快速在 iOS 和 Android 上构建高质量的原生用户界面。 Flutter 可以与现有的代码一起工作。
Flutter 具有以下特点：
快速开发，毫秒级的热重载，修改后，您的应用界面会立即更新。
统一的应用开发体验
原生性能
目前已经有不少大公司开始将 flutter 应用在项目中，比如，闲鱼、美团等，也得到了不错的反馈。
https://github.com/alibaba/flutter-go
文章暂时比较简单，之后各个模块可以细化

flutter 介绍及安装

对于构建 Flutter 类型应用，因其开发语言 Dart、虚拟机、构建工具与平时我们开发 Native 应用不同且平台虚拟机也不支持，所以需要 flutter sdk 来支持。
flutter 有点类似 gradle，不同的开发人员可能安装不同版本的 flutter，flutter sdk 版本不一致，往往会出现 Dart 层 Api 兼容性或 Flutter 虚拟机不一致等问题。（这个问题可以参照 Android gradle 管理，将 gradle 版本跟项目绑定来处理）

具体 flutter sdk 安装可以按照官方文档来操作：https://flutter.dev/docs/get-started/install/macos
或者 flutter 中文文档：https://flutterchina.club/setup-macos/

安装基本没有什么坑，有墙的问题可以参考中文文档使用 Flutter 官方为中国开发者搭建了临时镜像。

配置好就可以使用 flutter 的一些命令，比如 flutter doctor。

Flutter 四种工程类型

Flutter 工程中，通常有以下几种工程类型，下面分别简单概述下：

Flutter Application
标准的 Flutter App 工程，包含标准的 Dart 层与 Native 平台层

Flutter Module
Flutter 组件工程，仅包含 Dart 层实现，Native 平台层子工程为通过 Flutter 自动生成的隐藏工程

Flutter Plugin
Flutter 平台插件工程，包含 Dart 层与 Native 平台层的实现

Flutter Package
Flutter 纯 Dart 插件工程，仅包含 Dart 层的实现，往往定义一些公共 Widget

已有项目使用 flutter

已有的项目想改成纯 flutter 项目基本不可能，目前只能是开发部分模块功能使用，比如现在磁场项目中的体现功能。因此 flutter 官方出了向原生项目中添加 flutter 的项目：
https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps

目前想要的效果是：

非 flutter 开发人员无感知

对现有项目无侵入

不需要对现有的持续集成和编译发布进行修改

方便 flutter 开发人员开发

官方的项目是将 flutter 项目作为 module 来依赖，但是这对项目修改太大，只适用于开发人员。因此我们需要考虑其他的方式。在文档中我们知道，通过./gradlew flutter:assemble 是可以打包出 aar，这个 aar 其实是 flutter 生成的产物打包成 aar，来供项目使用的。我们可以利用这个，来只使用 aar，这样基本满足了上面的部分条件。但是如果是每次生成一个 aar 再拷贝到主项目 libs 下，这样每次处理太麻烦了，如果能将 aar 进行远程依赖就更好了，上面的要求基本就都满足了，对原生项目来说只是一个远程依赖而已，需要更新时则修改版本号即可。

至此，我们梳理出流程：

flutter aar 作为远端依赖

本地有配置是否是 flutter 开发环境

开启开发环境，则使用本地依赖方式

关闭开发环境，使用远端依赖

默认关闭

flutter 项目可自动打包上传 aar 至远端仓库

flutter module 的项目结构如下图：

.android 和 .ios 都是自动生成的，可以随时删除，通过flutter packages get 获取， flutter 代码主要在 lib 下。注意在.android 和.ios 目录下都有一个 Flutter 目录，这个是我们 flutter 的库项目了。也就是 Android 用来生成 aar，iOS 用来生产 framework 的库。如果我们用 flutter create xxx 生成的纯 flutter 项目是没有这个 Flutter 目录的。

开发遇到的坑

项目配置 productFlavor，导致无法将 flutter_assets 打包进 apk

其实这个是 flutter 的新版的 bug，flutter 的构建都是通过 flutter.gradle 来进行的，新的版本中做了一些改变，以为其中硬编码的原因，导致配置了 productFlavor 后无法执行某些 task，也就没有无法将 flutter_assets 打包进 apk。从而引起崩溃。

做了个临时解决方案：

创建代理 flutter 构建的 gradle 文件，即 flutter_proxy.gradle，从 flutter.gradle 复制而来

修改其关于配置了 productFlavor 后的执行 task 的逻辑，确保执行相关 productFlavor 的打包 task

在 build.gradle 中替换 flutter.gradle 为 flutter_proxy.gradle

这样就可以正常使用 gradle 打包了，缺点就是每次 flutter package get 需要重新改

注：该 Bug 在新版 flutter sdk 中已修复

还有个疑问就是 ./gradlew flutter:assemble 打出的 aar 安装后，原生页面打开 flutter 页面时崩溃，但是打包命令去掉 flutter 却可以，即 ./gradlew assemble，猜测跟打包流程有关系，暂时没有深入去研究

appbar 设置属性时默认设置了状态栏
解决办法：单独调整状态栏属性，或修改主题

flutter 项目中默认生成的 build.gradle 中依赖的是 support 27.1.1，目前项目中使用的是 26.1.0，导致包依赖冲突

对于远端依赖时可以移除他的 support 依赖，如下：

Copy
implementation('com.huazidev:test-futter-aar:0.0.2@aar', {
exclude group: 'com.android.support'
})

对于本地开发环境可以做如下配置：

Copy
implementation(project(':flutter')){
exclude group: 'com.android.support'
}

另外，也可以在 gradle 中统一修改所有的 support 依赖版本，

下一章，待完善

编写脚本，自动打包发布 aar

发布到 jcenter 、maven 等开源仓库

发布到自建的私有 maven 仓库

使用 jitpack 发布 （私有仓库收费）

使用 github 提供的功能作为包管理仓库（支持私有仓库）