浅谈 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依赖,如下:
1 | implementation('com.huazidev:test-futter-aar:0.0.2@aar', { |
对于本地开发环境可以做如下配置:
1 | implementation(project(':flutter')){ |
另外,也可以在 gradle 中统一修改所有的support依赖版本,
下一章,待完善
- 编写脚本,自动打包发布 aar
- 发布到jcenter 、maven等开源仓库
- 发布到自建的私有maven仓库
- 使用jitpack发布 (私有仓库收费)
- 使用github提供的功能作为包管理仓库(支持私有仓库)