浅谈 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工程中,通常有以下几种工程类型,下面分别简单概述下:

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

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

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

  4. 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 的项目结构如下图:

flutter_android_img.jpeg

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

开发遇到的坑

  1. 项目配置 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.gradleflutter_proxy.gradle

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

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

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

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

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

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

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

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

1
2
3
implementation(project(':flutter')){
exclude group: 'com.android.support'
}

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


下一章,待完善

  • 编写脚本,自动打包发布 aar
  • 发布到jcenter 、maven等开源仓库
  • 发布到自建的私有maven仓库
  • 使用jitpack发布 (私有仓库收费)
  • 使用github提供的功能作为包管理仓库(支持私有仓库)