Flutter Android 1.12 遷移指南

kassadin發表於2019-12-10

翻譯自 github.com/flutter/flu…

如果您在版本 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 專案,請遵循以下步驟:

  1. 刪除 android/app/src/main/java/[your/package/name]/MainActivity.java。如果你沒有新增過程式碼,那麼可以直接刪掉 [your/package/name]整個包結構,因為裡面只有MainActivity.java
  2. 開啟 android/app/src/main/AndroidManifest.xml.
  3. 從 application 標籤中刪除 FlutterApplication 的引用

修改前:

<application
  name="io.flutter.FlutterApplication"
  >
  <!-- code omitted -->
</application>
複製程式碼

修改後:

<application
  >
  <!-- code omitted -->
</application>
複製程式碼
  1. 修改 MainActivityFlutterActivity.

修改前:

<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>
複製程式碼
  1. 更新 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>
複製程式碼
  1. <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.FlutterFragmentio.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。

相關文章