Flutter Android 1.12 迁移指南
如果您在版本 1.12 之前是通过 flutter create
创建项目,则这可能适用于您的项目
背景
为了更好地支持将 Flutter 添加到现有项目的执行环境,托管 Flutter 运行时的旧版 Android 平台端包装器位于 io.flutter.app.FlutterActivity
及其关联的类现在已弃用。新的包装器 io.flutter.embedding.android.FlutterActivity
及相关类替代了他们。
这些类能更好地支持实际使用情况,如 FlutterActivity 可能不是应用程序中的第一个也不是唯一的 Android Activity。
Motivation
您现有的 Full-Flutter 项目不会立即受到影响,并且在可预见的将来将继续像以前一样工作。
但是,新的 Android 包装器还引入了一组新的 Android 插件开发 API。 仅在新插件 API 上开发的插件不适用于较早的 1.12 版 Android 项目。使用 1.12 之后创建的插件来构建 1.12 之前的 Android 项目,会产生构建时错误,除非该插件开发人员明确选择创建第二个向后兼容的实现。
旧版 Android API 尚未正式支持“Add-to-app”。 如果您在 1.12 之前遵循 Wiki 中关于“Add-to-app”的实验性说明,则应遵循下面 Add-to-app 部分 下的迁移步骤。
Full-Flutter 应用迁移
本指南假定您尚未手动为 Flutter 项目修改 Android host 项目。 如果您这样做了,请查阅下面的“add-to-app”迁移指南。
如果您选择迁移标准的 flutter create
项目,请遵循以下步骤:
- 删除
android/app/src/main/java/[your/package/name]/MainActivity.java
。如果你没有添加过代码,那么可以直接删掉[your/package/name]
整个包结构,因为里面只有MainActivity.java
。 - 打开
android/app/src/main/AndroidManifest.xml
. - 从 application 标签中删除
FlutterApplication
的引用
修改前:
<application
name="io.flutter.FlutterApplication"
>
<!-- code omitted -->
</application>
修改后:
<application
>
<!-- code omitted -->
</application>
- 修改
MainActivity
为FlutterActivity
.
修改前:
<activity android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@android:style/Theme.Black.NoTitleBar"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"
>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
修改后(只改了前 3 行):
<activity android:name="io.flutter.embedding.android.FlutterActivity"
android:theme="@android:style/Theme.Black.NoTitleBar"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"
>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
- 更新 Splash 页(如果需要初始行为)。
删除所有键为 android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
的<meta-data>
标签。
在 styles.xml
中添加一个启动主题,将所需的启动屏幕配置为背景`Drawable':
<!-- You can name this style whatever you'd like -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">@drawable/[your_launch_drawable_here]</item>
</style>
如果使用 Flutter create
创建 Flutter 项目,则可能已经定义了 LaunchTheme
以及一个名为 Launch_background
的可绘制对象。 您可以重新使用该配置并根据需要进行调整。
在 styles.xml
中添加一个普通主题,当 Android 进程完全初始化时,该主题会替换启动屏幕:
<!-- You can name this style whatever you'd like -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">@drawable/[your_normal_background_drawable]</item>
</style>
"normal theme" 为您的 Flutter 体验提供了背景。 通常会在第一个 Flutter 帧渲染之前的短暂时间内看到该背景。 在您的 Flutter 体验期间,"normal theme" 还控制 Android 的状态栏和导航栏的视觉属性。
配置 FlutterActivity
以 launch theme 启动,然后再切换到 normal theme。 还指定您希望启动屏幕继续显示,直到 Flutter 渲染其第一帧为止:
<activity android:name="io.flutter.embedding.android.FlutterActivity"
android:theme="@style/LaunchTheme"
// some code omitted
>
<!-- Specify that the launch screen should continue being displayed -->
<!-- until Flutter renders its first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background" />
<!-- Theme to apply as soon as Flutter begins rendering frames -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<!-- some code omitted -->
</activity>
- 在
<application>
下添加<meta-data>
标签。
<meta-data
android:name="flutterEmbedding"
android:value="2" />
您的应用仍应正常构建(例如通过 flutter build apk
构建),但是您现在正在使用新的 Android 类。
Add-to-app 迁移
本节详细介绍如何使用 Flutter 实验性嵌入构建的 add-to-app 场景,以及如何将该代码转换为 Flutter 新的稳定嵌入。
和 full-Flutter 一样的步骤
上面 Full-Flutter 应用迁移部分中的某些说明仍然适用。 请按照上述步骤操作:
3. 从 application 标签中删除 FlutterApplication
的引用
5. 更新 Splash 页(如果需要初始行为)。
6. 在 <application>
下添加 <meta-data>
标签。
特定于 add-to-app 的更改
如果你调用了 FlutterMain.startInitialization(...)
or FlutterMain.ensureInitializationComplete(...)
,应当删除。Flutter 现在会在适当的时间进行初始化。
迁移 FlutterActivity 使用
Add-to-app 场景通常涉及对 FlutterActivity
子类的修改。 例如,这种情况下可能会引入新的MethodChannel
,自定义 FlutterEngine
实例,自定义启动屏幕行为或其他要求覆盖现有方法的行为。 因此,尽管全 Flutter 应用程序可以删除其 MainActivity
并将其替换为标准FlutterActivity
,但您将需要保留子类,以便保留行为覆盖。
如果您未修改 FlutterActivity
中的行为,则应删除您的子类,并按照上一节中的描述将其替换为标准的 FlutterActivity
。
如果你需要修改 FlutterActivity
中的行为,你需要将代码从旧的 io.flutter.app.FlutterActivity
迁移到新的 io.flutter.embedding.android.FlutterActivity
。
From:
package [your.package.name];
import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
// ...some amount of custom code for your app is here.
}
To:
package [your.package.name];
import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterActivity {
// 不再需要重写 onCreate 来调用 GeneratedPluginRegistrant
// You do not need to override onCreate() in order to invoke
// GeneratedPluginRegistrant. Flutter now does that on your behalf.
// ...retain whatever custom code you had from before (if any).
}
一些应用可能需要预热 Flutter 体验,现在建议在初次呈现 Flutter UI 时,所有 add-to-app 的用例都应使 Flutter 预热,以达到最佳视觉效果。参考 Flutter guide for pre-warming a FlutterEngine (TODO: mattcarroll,还没写…) 更新你的代码来预热 Flutter。
您的 FlutterActivity
子类现在已使用最新的、稳定的 Android embedding 了
迁移 FlutterFragment 使用
实验性嵌入提供了一个名为 io.flutter.facade.FlutterFragment
的类,以及io.flutter.facade
包中的其他类。 整个 io.flutter.facade
软件包已被弃用,您不应使用其中的任何类。
实验性的 io.flutter.facade.FlutterFragment
被io.flutter.embedding.android.FlutterFragment
所取代,它被设计用于比原始的FlutterFragment
更广泛的用例集合。
如果使用了 Flutter.createFragment(...)
实例化 io.flutter.facade.FlutterFragment
,则应删除这样的调用,并通过以下任一方法实例化新的io.flutter.embedding.android.FlutterFragment
:
FlutterFragment.createDefault()
FlutterFragment.withNewEngine()
FlutterFragment.withCachedEngine(...)
这些工厂方法的使用已在以下网站的网站指南中进行了深入讨论: flutter.dev.
迁移 FlutterView 使用
已弃用的 io.flutter.facade.Flutter
类具有一个名为 createView(...)
的工厂方法,也已弃用,以及 io.flutter.facade
软件包中的所有其他代码。
Flutter目前不提供在View级别使用Flutter的便捷API,因此如果可能,应避免使用 FlutterView
。 但是如果需要的话,显示 FlutterView
在技术上是可行的。 确保使用io.flutter.embedding.android.FlutterView
而不是 io.flutter.view.FlutterView
。 您可以像其他任何Android View
一样实例化新的 FlutterView
。 然后,按照相关Javadocs中的说明通过 FlutterView
显示Flutter。
转载自:https://juejin.cn/post/6844904017857003527