混合开发方式:
一、源码集成
二、产物集成:Flutter 项目单独开发,开发完成后发布成 aar 包或者 IOS的 framework 形式,原生项目依赖 Flutter 输出的制品即可
产物集成
在已有Andriod项目中集成Flutter
1、创建Android项目
步骤忽略。
2、安卓Studio配置Flutter
请参考另一篇文章:安卓studio 配置Flutter
3、创建flutter module
打开安卓项目,Terminal调整位置至项目目录使用命令flutter create -t module {项目名称}
创建Flutter module。
例如:flutter create -t module myflutter
会出现:
Creating project myflutter...
myflutter\.gitignore (created)
myflutter\.idea\libraries\Dart_SDK.xml (created)
myflutter\.idea\modules.xml (created)
myflutter\.idea\workspace.xml (created)
myflutter\.metadata (created)
myflutter\analysis_options.yaml (created)
myflutter\lib\main.dart (created)
myflutter\myflutter.iml (created)
myflutter\myflutter_android.iml (created)
myflutter\pubspec.yaml (created)
myflutter\README.md (created)
myflutter\test\widget_test.dart (created)
Running "flutter pub get" in myflutter... 1,844ms
Wrote 12 files.
到此你会发现项目中多了一个flutter的module如下图:
注意:
在 Flutter 的模块项目中包含有一个隐藏的 .android
和 .ios
目录这个目录下是可运行的 Android
和 iOS
项目,我们的 Flutter
代码还是在 lib
下编写,注意在 .android
和 .ios
目录下都有一个 Flutter
目录,这个是我们 Flutter 的库项目了。也就是 Android
用来生成 aar
, IOS
用来生产 framework
的库。如果我们用 flutter create xxx
生成的纯 Flutter 项目是没有这个 Flutter 目录的。
如果不是通过flutter create -t module 名称
方式创建的module的话,在flutter module 中的.android中会缺少include_flutter.groovy文件,这就会导致
evaluate(new File(
// '{xxxxx你的flutter module目录}/.android/include_flutter.groovy'
'myflutter/.android/include_flutter.groovy'
))
这一步报错
对比如下:
(1)通过flutter create -t module myflutter
创建的Flutter项目组成
(2)直接 create new fluter project
4.将flutter module 提交至git
很多时候的开发都需要团队协作,这就面临着Flutter module的共享,下面以Gitee为例,将Flutter module分享者Git。
(1)修改忽略文件.gitignore
修改Flutter module的.gitignore文件内容如下:
.DS_Store
.dart_tool/
.packages
.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/
.android/
.ios/
.flutter-plugins
(2)提交代码至Git
使用安卓studio单独打开flutter module,VCS
- Import Into Version Contral
- Share Project On Gitee
提交后登录Gitee官网,招到对应的项目,复制仓库地址。
5. 给原生 Android 项目集成 Flutter Module
方案一(直接引用到项目中):
其他同事需要共享flutter module的时候,通过以下操作:
1.在原生 Android 项目中添加子模块,将上面创建的 flutter module 项目拉取到原生安卓项目中
引入已有的Flutter module:
git submodule add {你的flutter module的仓库地址}
git submodule update
此处要保证module和安卓项目在同一级文件目录下
这时有可能报错:
E:\Flutter\MuFlutterAndroidProject2>git submodule add https://gitee.com/wen__flower/myflutter.git
fatal: not a git repository (or any of the parent directories): .git
这时候进入到安卓项目文件夹中,右键Git Bash Here 之后输入git init即可。
2.在根目录的 settings.gradle
中添加如下配置
include ':app'
setBinding(new Binding([gradle: this]))
evaluate(new File(
// '{xxxxx你的flutter module目录}/.android/include_flutter.groovy'
'myflutter/.android/include_flutter.groovy'
))
3.在原生项目的 app 目录下的 build.gradle
文件中添加 Flutter 库的依赖
dependencies {
implementation project(':flutter')
}
4.实现基础的跳转
//默认跳转到Flutter -main页面
startActivity(FlutterActivity.createDefaultIntent(this));
记得要在清单文件里面注册:
<activity android:name="io.flutter.embedding.android.FlutterActivity"/>
但是这时候有个问题就是从原生跳转到Flutter的时候速度很慢
可以采用将页面存起来的方式来加快速度:
class MyApp : Application(){
lateinit var flutterEngine : FlutterEngine
override fun onCreate() {
super.onCreate()
flutterEngine = FlutterEngine(this)
// 可设置初始路由
// flutterEngine.getNavigationChannel().setInitialRoute("your/route/here");
flutterEngine.dartExecutor.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault())
FlutterEngineCache
.getInstance()
.put("AndLangFlutter", flutterEngine)
}
// 释放flutter引擎
override fun onTerminate() {
flutterEngine.destroy()
super.onTerminate()
}
}
跳转的时候采用:
startActivity(
FlutterActivity
.withCachedEngine("AndLangFlutter")
.build(this)
)
此时运行会报错:Error: No pubspec.yaml file found.
查看flutter module目录也会发现,文件目录不完整。
解决办法:
在安卓项目的Terminal中将目录地址调整至flutter module文件目录,(例如:cd myflutter
回车)
在使用flutter packages get
可解决。
总结:
这种方案,不太适合合作开发,由于合作开发要求flutter module单独维护,他有自己的git库,同时flutter module内嵌在安卓项目里面 ,各自有各自的git库,更新代码不方便
方案二(依赖本地仓库) :
flutter module和安卓项目分开,等于说是两个项目
1、操作flutter module生成aar
打开flutter module项目 build - Flutter -Build AAR
等待生成文件
产生如下打印信息:
Running Gradle task 'assembleAarProfile'... 7.3s
√ Built build\host\outputs\repo.
Running Gradle task 'assembleAarRelease'... 7.6s
√ Built build\host\outputs\repo.
Consuming the Module
1. Open <host>\app\build.gradle
2. Ensure you have the repositories configured, otherwise add them:
String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?: "https://storage.googleapis.com"
repositories {
maven {
url 'E:\flutterproject\FlutterAndAndroid\gas-ent-flutter-app\build\host\outputs\repo'
}
maven {
url "$storageUrl/download.flutter.io"
}
}
3. Make the host app depend on the Flutter module:
dependencies {
debugImplementation 'com.example.gas_client_flutter:flutter_debug:1.0'
profileImplementation 'com.example.gas_client_flutter:flutter_profile:1.0'
releaseImplementation 'com.example.gas_client_flutter:flutter_release:1.0'
}
4. Add the `profile` build type:
android {
buildTypes {
profile {
initWith debug
}
}
}
To learn more, visit https://flutter.dev/go/build-aar
Process finished with exit code 0
2、按照提示在安卓项目中配置相关信息
(1)
(2)
(3)
方案三:(不依赖本地仓库) 推荐
找到你的flutter module项目目录下的build/host/outputs/repo,将flutter_release-1.0.aar复制到android项目下
2、打开你的安卓工程,将aar copy到libs目录下
3、app build.grade配置
repositories {
flatDir {
dirs 'libs' // aar目录
}
}
添加如下:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation(name: 'flutter_release-1.0', ext: 'aar')
implementation 'io.flutter:flutter_embedding_release:1.0.0-626244a72c5d53cc6d00c840987f9059faed511a'
implementation 'io.flutter:armeabi_v7a_release:1.0.0-626244a72c5d53cc6d00c840987f9059faed511a'
implementation 'io.flutter:arm64_v8a_release:1.0.0-626244a72c5d53cc6d00c840987f9059faed511a'
implementation 'io.flutter:x86_64_release:1.0.0-626244a72c5d53cc6d00c840987f9059faed511a'
}
注意:1.0.0-626244a72c5d53cc6d00c840987f9059faed511a 来自哪里呢?
姿势:找到flutter根目录下的build/host/outputs/repo, 将flutter_release-1.0.pom,里面有如下flutter基础库的地址
<groupId>com.example.flutter_library</groupId>
<artifactId>flutter_release</artifactId>
<version>1.0</version>
<packaging>aar</packaging>
<dependencies>
<dependency>
<groupId>io.flutter.plugins.sharedpreferences</groupId>
<artifactId>shared_preferences_release</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.flutter</groupId>
<artifactId>flutter_embedding_release</artifactId>
<version>1.0.0-626244a72c5d53cc6d00c840987f9059faed511a</version>
<scope>compile</scope>
</dependency>
4、外层build.grade配置
buildscript {
repositories {
google()
jcenter()
maven {
url "http://download.flutter.io"
}
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.0'
}
}
5、组件化工程通常是在某个module/lib下依赖,比如module_flutter
在module_flutter build.gradle下配置
repositories {
flatDir {
dirs 'libs' // aar目录
}
}
在主App 下配置
repositories {
// 详细路径
flatDir {
dirs 'libs', '../module_flutter/libs'
}
}
6、在你的MainActivity 加入如下代码
import androidx.appcompat.app.AppCompatActivity;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.view.FlutterMain;
/**
* 原生安卓跳转Flutter
*/
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
FlutterMain.startInitialization(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startActivity(FlutterActivity.createDefaultIntent(this));
}
}
7、在你的清单文件中加入FlutterActivity,注意导包io.flutter.embedding.android
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androiddemo">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:name=".FlutterApplication"
android:theme="@style/AppTheme">
<activity android:name="io.flutter.embedding.android.FlutterActivity"/>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>