Native 如何快速集成 Flutter
如何 Android 项目中集成 Flutter
概述
目前flutter越来越受欢迎,但对于一些成熟的产品来说,完全摒弃原有App全面转向Flutter是不现实的。因此使用Flutter去统一Android、iOS技术栈,把它作为已有原生App的扩展能力,通过有序推进来提升移动终端的开发效率。 目前,想要在已有的原生App里嵌入一些Flutter页面主要有两种方案。一种是将原生工程作为Flutter工程的子工程,由Flutter进行统一管理,这种模式称为统一管理模式。另一种是将Flutter工程作为原生工程的子模块,维持原有的原生工程管理方式不变,这种模式被称为三端分离模式,如下图所示。
三端代码分离模式的原理是把Flutter模块作为原生工程的子模块,从而快速地接入Flutter模块,降低原生工程的改造成本。
如何在Native项目中接入flutter 模块
在原生项目中集成flutter模块有两种方式,第一种是直接在项目中新建一个flutter module,第二种将flutter项目模块打包成aar或so包集成到Native项目中。一下将详细介绍这两种方式 (以Android为例)
采用module引用的方式
直接通过Android stuido
File->New ->New Module 选择 Flutter Module 来生成一个Flutter Module.
如下图:Android studio为原生项目创建了一个module
手动创建Flutter module
假设你在 some/path/MyApp
路径下已有一个 Android 应用,并且你希望 Flutter 项目作为同级项目:
cd some/path/
$ flutter create -t module --org com.example my_flutter
注意:
- 这会创建一个
some/path/my_flutter/
的 Flutter 模块项目,其中包含一些 Dart 代码来帮助你入门以及一个隐藏的子文件夹.android/
。.android
文件夹包含一个 Android 项目,该项目不仅可以帮助你通过flutter run
运行这个 Flutter 模块的独立应用,而且还可以作为封装程序来帮助引导 Flutter 模块作为可嵌入的 Android 库。 - 为了避免 Dex 合并出现问题,
flutter.androidPackage
不应与应用的包名相同
引入 Java 8
Flutter Android 引擎需要使用到 Java 8 中的新特性。
在尝试将 Flutter 模块项目集成到宿主 Android 应用之前,请先确保宿主 Android 应用的 build.gradle 文件的 android { }
块中声明了以下源兼容性,例如:
android {
//...
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
}
采用AAR资源包的方式导入Flutter模块
flutter 工程作为独立的项目开发迭代,原生工程不直接使用Flutter项目,而是通过导入flutter 的资源包来引用Flutter 模块。
创建Flutter module 工程。
编译生成AAR包
flutter 工程会创建一个本地maven仓库和aar文件,同时在Flutter 项目也会输出指引导入的步骤文本,按照提示步骤操作即可。
为方便使用将该maven仓库拷贝到native 项目中。
提示步骤如下
Consuming the Module
Open \app\build.gradle
Ensure you have the repositories configured, otherwise add them:
String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?: "storage.googleapis.com"
repositories {
maven {
url 'D:<path>\build\host\outputs\repo'
}
maven {
url '$storageUrl/download.flutter.io'
}
}Make the host app depend on the Flutter module:
dependencies {
debugImplementation 'com.example.untitled1:flutter_debug:1.0'
profileImplementation 'com.example.untitled1:flutter_profile:1.0'
releaseImplementation 'com.example.untitled1:flutter_release:1.0'
}
- Add the
profile
build type:
android {
buildTypes {
profile {
initWith debug
}
}
}
To learn more, visit flutter.dev/go/build-aa…
Process finished with exit code 0
在 Android 应用中添加 Flutter 页面
步骤 1:在 AndroidManifest.xml 中添加 FlutterActivity
Flutter 提供了 FlutterActivity
,用于在 Android 应用内部展示一个 Flutter 的交互界面。和其他的 Activity
一样,FlutterActivity
必须在项目的 AndroidManifest.xml
文件中注册。将下边的 XML 代码添加到你的 AndroidManifest.xml
文件中的 application
标签内:
<activity
android:name="io.flutter.embedding.android.FlutterActivity"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"
/>
上述代码中的 @style/LaunchTheme
可以替换为想要在你的 FlutterActivity
中使用的其他 Android 主题。主题的选择决定 Android 系统展示框架所使用的颜色,例如 Android 的导航栏,以及 Flutter UI 自身的第一次渲染前 FlutterActivity
的背景色。
步骤 2:加载 FlutterActivity
在你的清单文件中注册了 FlutterActivity
之后,根据需要,你可以在应用中的任意位置添加打开 FlutterActivity
的代码。下边的代码展示了如何在 OnClickListener
的点击事件中打开 FlutterActivity
。
myButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startActivity(
FlutterActivity.createDefaultIntent(currentActivity)
);
}
});
Flutter 启动优化
每一个 FlutterActivity
默认会创建它自己的 FlutterEngine
。每一个 FlutterEngine
会有一个明显的预热时间。这意味着加载一个标准的 FlutterActivity
时,在你的 Flutter 交互页面可见之前会有一个短暂的延迟。想要最小化这个延迟时间,你可以在抵达你的 FlutterActivity
之前,初始化一个 FlutterEngine
,然后使用这个已经预热好的 FlutterEngine
。
如果直接启动FlutterActivity则无法避免预热时间,用户会感受到一个较长时间的白屏等待。
优化
提前初始化一个 FlutterEngine
,启动的FlutterActivty时直接使用已经初始化的FlutterEngine
.
提前初始化
public class MyApplication extends Application {
public FlutterEngine flutterEngine;
@Override
public void onCreate() {
super.onCreate();
// Instantiate a FlutterEngine.
flutterEngine = new FlutterEngine(this);
// Start executing Dart code to pre-warm the FlutterEngine.
flutterEngine.getDartExecutor().executeDartEntrypoint(
DartEntrypoint.createDefault()
);
// Cache the FlutterEngine to be used by FlutterActivity.
FlutterEngineCache
.getInstance()
.put("my_engine_id", flutterEngine);
}
}
使用预热的FlutterEngine
myButton.addOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startActivity(
FlutterActivity
.withCachedEngine("my_engine_id")
.build(currentActivity)
);
}
});
作者:hujian
链接:https://juejin.cn/post/7113874811675213832
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。