将 Flutter 屏幕添加到 Android 应用程序
本指南介绍如何将单个 Flutter 屏幕添加到现有的 Android 应用程序。Flutter 屏幕可以作为普通的不透明屏幕添加,也可以作为透明的半透明屏幕添加。本指南中介绍了这两种选择。
添加一个正常的 Flutter 屏幕
步骤 1:将 FlutterActivity 添加到 AndroidManifest.xml
Flutter 提供 FlutterActivity
在 Android 应用程序中显示 Flutter 体验。与任何其他 Activity
一样,FlutterActivity
必须在 AndroidManifest.xml
中注册。将以下 XML 添加到 application
标记下的 AndroidManifest.xml
文件中
<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)
);
}
});
myButton.setOnClickListener {
startActivity(
FlutterActivity.createDefaultIntent(this)
)
}
前面的示例假定您的 Dart 入口点称为 main()
,并且您的初始 Flutter 路由为“/”。无法使用 Intent
更改 Dart 入口点,但可以使用 Intent
更改初始路由。以下示例演示如何启动一个 FlutterActivity
,该活动最初在 Flutter 中呈现自定义路由。
myButton.addOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startActivity(
FlutterActivity
.withNewEngine()
.initialRoute("/my_route")
.build(currentActivity)
);
}
});
myButton.setOnClickListener {
startActivity(
FlutterActivity
.withNewEngine()
.initialRoute("/my_route")
.build(this)
)
}
将 "/my_route"
替换为您所需的初始路由。
使用 withNewEngine()
工厂方法可以配置 FlutterActivity
,它会在内部创建自己的 FlutterEngine
实例。这会带来不小的初始化时间。另一种方法是指示 FlutterActivity
使用预热缓存的 FlutterEngine
,这可以最大程度缩短 Flutter 的初始化时间。接下来将讨论这种方法。
步骤 3:(可选) 使用缓存的 FlutterEngine
默认情况下,每个 FlutterActivity
都会创建自己的 FlutterEngine
。每个 FlutterEngine
都具有不小的预热时间。这意味着启动标准 FlutterActivity
会在您的 Flutter 体验可见之前带来短暂延迟。为了最大程度缩短此延迟,您可以在到达 FlutterActivity
之前预热 FlutterEngine
,然后可以使用预热的 FlutterEngine
。
要预热 FlutterEngine
,请在您的应用中找到一个合适的位置来实例化 FlutterEngine
。以下示例在 Application
类中预热 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);
}
}
class MyApplication : Application() {
lateinit var flutterEngine : FlutterEngine
override fun onCreate() {
super.onCreate()
// Instantiate a FlutterEngine.
flutterEngine = FlutterEngine(this)
// Start executing Dart code to pre-warm the FlutterEngine.
flutterEngine.dartExecutor.executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
)
// Cache the FlutterEngine to be used by FlutterActivity.
FlutterEngineCache
.getInstance()
.put("my_engine_id", flutterEngine)
}
}
传递给 FlutterEngineCache
的 ID 可以是您想要的任何内容。请确保将相同的 ID 传递给应使用缓存的 FlutterEngine
的任何 FlutterActivity
或 FlutterFragment
。接下来将讨论使用缓存的 FlutterEngine
的 FlutterActivity
。
使用预热缓存的 FlutterEngine
,你现在需要指示你的 FlutterActivity
使用缓存的 FlutterEngine
,而不是创建一个新的。要实现此目的,请使用 FlutterActivity
的 withCachedEngine()
构建器
myButton.addOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startActivity(
FlutterActivity
.withCachedEngine("my_engine_id")
.build(currentActivity)
);
}
});
myButton.setOnClickListener {
startActivity(
FlutterActivity
.withCachedEngine("my_engine_id")
.build(this)
)
}
使用 withCachedEngine()
工厂方法时,传递与缓存所需的 FlutterEngine
时使用的相同的 ID。
现在,当你启动 FlutterActivity
时,Flutter 内容的显示延迟会大大减少。
使用缓存引擎的初始路由
在使用新的 FlutterEngine
配置 FlutterActivity
或 FlutterFragment
时,可以使用初始路由的概念。但是,当使用缓存引擎时,FlutterActivity
和 FlutterFragment
不提供初始路由的概念。这是因为缓存引擎预计已经运行 Dart 代码,这意味着配置初始路由为时已晚。
希望缓存引擎从自定义初始路由开始的开发者可以在执行 Dart 入口点之前,将缓存的 FlutterEngine
配置为使用自定义初始路由。以下示例演示了在缓存引擎中使用初始路由
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// Instantiate a FlutterEngine.
flutterEngine = new FlutterEngine(this);
// Configure an initial route.
flutterEngine.getNavigationChannel().setInitialRoute("your/route/here");
// Start executing Dart code to pre-warm the FlutterEngine.
flutterEngine.getDartExecutor().executeDartEntrypoint(
DartEntrypoint.createDefault()
);
// Cache the FlutterEngine to be used by FlutterActivity or FlutterFragment.
FlutterEngineCache
.getInstance()
.put("my_engine_id", flutterEngine);
}
}
class MyApplication : Application() {
lateinit var flutterEngine : FlutterEngine
override fun onCreate() {
super.onCreate()
// Instantiate a FlutterEngine.
flutterEngine = FlutterEngine(this)
// Configure an initial route.
flutterEngine.navigationChannel.setInitialRoute("your/route/here");
// Start executing Dart code to pre-warm the FlutterEngine.
flutterEngine.dartExecutor.executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
)
// Cache the FlutterEngine to be used by FlutterActivity or FlutterFragment.
FlutterEngineCache
.getInstance()
.put("my_engine_id", flutterEngine)
}
}
通过设置导航通道的初始路由,关联的 FlutterEngine
在 runApp()
Dart 函数的初始执行时显示所需的路由。
在 runApp()
的初始执行后更改导航通道的初始路由属性无效。希望在不同的 Activity
和 Fragment
之间使用相同的 FlutterEngine
并切换这些显示之间的路由的开发者需要设置一个方法通道,并明确指示其 Dart 代码更改 Navigator
路由。
添加一个半透明的 Flutter 屏幕
大多数全屏 Flutter 体验都是不透明的。但是,一些应用希望部署看起来像模态的 Flutter 屏幕,例如对话框或底部工作表。Flutter 支持开箱即用的半透明 FlutterActivity
。
要使 FlutterActivity
半透明,请对创建和启动 FlutterActivity
的常规流程进行以下更改。
步骤 1:使用具有半透明的主题
对于使用半透明背景渲染的 Activity
,Android 需要一个特殊的主题属性。使用以下属性创建或更新 Android 主题
<style name="MyTheme" parent="@style/MyParentTheme">
<item name="android:windowIsTranslucent">true</item>
</style>
然后,将半透明主题应用于 FlutterActivity
。
<activity
android:name="io.flutter.embedding.android.FlutterActivity"
android:theme="@style/MyTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"
/>
您的 FlutterActivity
现在支持半透明。接下来,您需要使用显式透明度支持启动 FlutterActivity
。
步骤 2:使用透明度启动 FlutterActivity
要启动具有透明背景的 FlutterActivity
,请将适当的 BackgroundMode
传递给 IntentBuilder
// Using a new FlutterEngine.
startActivity(
FlutterActivity
.withNewEngine()
.backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.transparent)
.build(context)
);
// Using a cached FlutterEngine.
startActivity(
FlutterActivity
.withCachedEngine("my_engine_id")
.backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.transparent)
.build(context)
);
// Using a new FlutterEngine.
startActivity(
FlutterActivity
.withNewEngine()
.backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.transparent)
.build(this)
);
// Using a cached FlutterEngine.
startActivity(
FlutterActivity
.withCachedEngine("my_engine_id")
.backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.transparent)
.build(this)
);
现在,您拥有一个具有透明背景的 FlutterActivity
。