原生Android和Flutter集成主要有两种方案:
1.源码集成:官方提供的源码集成方案
2.产物集成:Flutter 项目单独开发,开发完成后发布成 aar 包或者 iOS 的 framework 形式,原生项目依赖 Flutter 输出的文件即可。
3.咸鱼团队的FlutterBoost 方案。FlutterBoost地址
环境
首先确认环境是否正确:
这里重点关注一下Flutter version的版本。在后面介绍集成开发的时候,不同的Flutter版本有差别。
flutter doctor -v
下面是我的环境信息:
集成
创建Android项目
略过新建 Native Android项目的流程。
注意点:
(1)现在创建的Flutter module默认是支持Android X的,所以如果想在现有的项目中集成Flutter module需要把support包替换成Android x。所有这里是通过新建一个 Native Android项目(默认支持Android x)来演示混合开发流程。
(2)配置信息,需要在app/build.gradle里设置
android {
//...
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
}
创建Flutter module
- 切换 flutter 的 channel 到 master (master 分支下是 flutter 的 preview 版本)
flutter channel master
- 创建 flutter module项目
module后面是新建的Flutter module的名称。
flutter create -t module flutter_test
- Flutter module的目录结构:
(1)在 flutter 的模块项目中包含有一个隐藏的 .android 和 .ios 目录这个目录下是可运行的 Android 和 iOS 项目。
(2)flutter代码写在 lib下,注意在 .android 和 .ios 目录下都有一个 Flutter 目录,这个是我们 flutter 的库项目了。也就是Android 用来生成 aar,iOS 用来生产 framework 的库。
(3 Flutter Application项目是没有.android 和.ios目录的。Flutter Application项目下对应的是android和ios这两个目录。
- git管理Flutter module
(1)把项目使用 git 管理起来,后面会在 native 项目中以submodule的形式引入native项目。
略过git上传到远程git仓库的过程。
(2)重点关注一下gitignore文件的编辑
编辑一下项目下的 .gitignore 文件,需要把项目下的 .ios 和 .android 忽略掉。
这里有个坑,有的文章说要把.packages也忽略掉,但是根据我的实验是不行的,建议大家还是把.packages通过git管理起来。
(3)我的gitignore配置信息
.DS_Store
.dart_tool/
.pub/
.idea/
.vagrant/
.sconsign.dblite
.svn/
*.swp
profile
DerivedData/
.generated/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
build/
.ios/Flutter/Generated.xconfig
.flutter-plugins
Native Android 项目集成 Flutter
- native android 项目集成 Flutter
(1)将目录切换到native android代码目录下
(2)将Flutter module添加到native android中。
git submodule add flutter module的仓库地址
git submodule update
- 在native android根目录的 settings.gradle中添加如下配置
这里的路径使用的是相对于native android 项目的路径。
setBinding(new Binding([gradle: this]))
evaluate(new File(
settingsDir,
'flutter_test/.android/include_flutter.groovy'
))
- 在native android项目的 app 目录下的 build.gradle 文件中添加 Flutter 库的依赖
implementation project(':flutter')
- 从新rebuild项目以后,在native android项目目录下会多一个flutter module子项目。
代码编写
通过native怎么加载flutter widget呢?Flutter提供了以下集中方法。(Flutter不同版本存在差异)
6.1 通过FlutterFragment类
直接在对应的native activity 布局文件中添加FlutterFragment即可。
6.2 通过FlutterActivity类
在 AndroidManifest.xml 中注册
默认启动方式:默认路由为 '/'
import io.flutter.embedding.android.FlutterActivity
val intent = FlutterActivity.createDefaultIntent(this)
startActivity(intent)
启动到指定路由
val customFlutter = FlutterActivity.withNewEngine()
.initialRoute("newRoute")
.build(this)
startActivity(customFlutter)
6.3 通过FlutterView类
通过该类没有实现效果,待研究
FlutterView flutterView = new FlutterView(this);
FrameLayout frameLayout = findViewById(R.id.framelayout);
frameLayout.addView(flutterView);
//创建一个 FlutterView 就可以了,这个时候还不会渲染。
//调用下面代码后才会渲染
flutterView.attachToFlutterEngine(new FlutterEngine(this));
集成中经历的坑
- finished with non-zero exit value 1
Process 'command '/Users/mtdp/Documents/Flutter/flutter/bin/flutter'' finished with non-zero exit value 1
造成这个的原因是缺少.packages文件,所有在通过git管理flutter module的时候,尽量把.packages保留。
- 废弃类
Flutter默认在某个版本以后已经不支持facade了。
在Flutter version 1.7.8+hotfix.4
版本还是支持的,具体从那个版本移除了,还不清楚。
io.flutter.facade.*
ps:以前的方式(deprecated) ( io.flutter.facade )
通过使用 Flutter.createView:
View flutterView = Flutter.createView(
MainActivity.this,
getLifecycle(),
"route1"
);
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(600, 800);
layout.leftMargin = 100;
layout.topMargin = 200;
addContentView(flutterView, layout);
通过使用 Flutter.createFragment:
FragmentTransaction tx = getSupportFragmentManager().beginTransaction();
tx.replace(R.id.someContainer, Flutter.createFragment("route1"));
tx.commit();
git submodule删除后重新添加问题
- 重新添加git 子模块出现的问题:
A git directory for 'formRenderLib' is found locally with remote(s):
origin xxxxxx
If you want to reuse this local git directory instead of cloning again from
xxxx
use the '--force' option. If the local git directory is not the correct repo
or you are unsure what this means choose another name with the '--name' option.
说明没有删除干净之前的module
-
解决方法:
2.1 在native android主项目目录下,删除指定模块的文件
git rm --cached module名称
2.2 打开主项目目录下 .gitmodules 删除和submodule相关的配置信息
2.3 打开主项目目录下 .git/config 文件删除和submodule相关的配置信息
2.4 删除.git下的缓存模块
rm -rf .git/modules/submodule名称
2.5 添加子模块
git submodule add submodule的git仓库