<

据え置きコンポーネント

序章

Flutter には、次のようなアプリを構築する機能があります。 実行時に追加の Dart コードとアセットをダウンロードします。 これにより、アプリはインストール APK サイズとダウンロードを減らすことができます ユーザーが必要なときに機能と資産を提供します。

個別にダウンロード可能な Dart の各バンドルを指します。 ライブラリとアセットを「遅延コンポーネント」として扱います。 これは、Dart の遅延インポートを使用して実現されます。 これは、分割された AOT 共有ライブラリにコンパイルできます。

モジュールは遅延ロードできますが、 アプリケーション全体が完全に構築されている必要があり、 単一の Android アプリ バンドルとしてアップロードされます。 再アップロードせずに部分的な更新をディスパッチする アプリケーション全体の新しい Android アプリ バンドル はサポートされていません。

遅延読み込みは、アプリが次の場合にのみ実行されます。 にコンパイルされますリリースモードまたはプロファイルモード。 デバッグ モードでは、すべての遅延コンポーネントが処理されます。 正規輸入品なので存在します 起動時にすぐにロードされます。したがって、 デバッグ ビルドは引き続きホット リロードできます。

技術的な詳細をさらに詳しく知るには、 この機能がどのように機能するかについては、を参照してください。延期されたコンポーネントで flutterウィキ。

遅延コンポーネント用にプロジェクトを設定する方法

次の手順では、セットアップ方法について説明します。 遅延読み込み用の Android アプリ。

ステップ 1: 依存関係とプロジェクトの初期セットアップ

  1. Android アプリに Play Core を追加する build.gradle の依存関係。 のandroid/app/build.gradle以下を追加します。

    ...
    dependencies {
      ...
      implementation "com.google.android.play:core:1.8.0"
      ...
    }
    
  2. Google Play ストアを 動的特徴の分散モデル、 アプリはサポートする必要がありますSplitCompatそしてインスタンスを提供します のPlayStoreDeferredComponentManager。 これらのタスクは両方とも、次のように設定することで実行できます。 のandroid:nameアプリケーションのプロパティandroid/app/src/main/AndroidManifest.xmlio.flutter.embedding.android.FlutterPlayStoreSplitApplication:

    <manifest ...
      <application
         android:name="io.flutter.embedding.android.FlutterPlayStoreSplitApplication"
            ...
      </application>
    </manifest>
    

    io.flutter.app.FlutterPlayStoreSplitApplicationハンドル これらのタスクはどちらもあなたに代わって行われます。使用する場合FlutterPlayStoreSplitApplication、 ステップ 1.3 に進んでください。

    Android アプリケーションの場合 大規模または複雑な場合は、個別にサポートする必要があるかもしれませんSplitCompatそして、PlayStoreDynamicFeatureManager手動で。

    サポートするSplitCompat、方法は3つあります (詳細はAndroid ドキュメント)、いずれも有効です。

    • アプリケーションのクラスを拡張するSplitCompatApplication:

      public class MyApplication extends SplitCompatApplication {
          ...
      }
      
    • 電話SplitCompat.install(this);の中にattachBaseContext()方法:

      @Override
      protected void attachBaseContext(Context base) {
          super.attachBaseContext(base);
          // Emulates installation of future on demand modules using SplitCompat.
          SplitCompat.install(this);
      }
      
    • 宣言するSplitCompatApplicationアプリケーションとして をサブクラス化し、Flutter 互換性コードを追加します。FlutterApplicationアプリケーションクラスに以下を追加します。

      <application
          ...
          android:name="com.google.android.play.core.splitcompat.SplitCompatApplication">
      </application>
      

    エンベッダーは注入されたものに依存しますDeferredComponentManager処理するインスタンス 延期されたコンポーネントのインストール要求。 を提供するPlayStoreDeferredComponentManagerの中へ 次のコードを追加して Flutter エンベッダーを作成します アプリの初期化に:

    import io.flutter.embedding.engine.dynamicfeatures.PlayStoreDeferredComponentManager;
    import io.flutter.FlutterInjector;
    ... 
    PlayStoreDeferredComponentManager deferredComponentManager = new
      PlayStoreDeferredComponentManager(this, null);
    FlutterInjector.setInstance(new FlutterInjector.Builder()
        .setDeferredComponentManager(deferredComponentManager).build());
    
  3. 追加して遅延コンポーネントをオプトインします のdeferred-componentsアプリへのエントリーpubspec.yamlflutterエントリ:

      ...
      flutter:
        ...
        deferred-components:
        ...
    

    flutterツールが探しますdeferred-componentsのエントリpubspec.yamlかどうかを判断します。 アプリは遅延としてビルドするかどうかを指定する必要があります。 まだ実行していない限り、今のところは空のままにしておいてかまいません 必要なコンポーネントと Dart 遅延ライブラリを知っている それがそれぞれに入ります。このセクションは後で入力します のステップ3.3一度gen_snapshotローディングユニットを生成します。

ステップ 2: 遅延 Dart ライブラリの実装

次に、遅延ロードされた Dart ライブラリを アプリのダーツコード。実装には必要ありません 機能はまだ完成していません。の例では、 このページの残りの部分では、新しい単純な遅延ウィジェットを追加します プレースホルダーとして。既存のコードを変換することもできます インポートと 遅延コードビハインドの使用を保護するloadLibrary() Futures

  1. 新しい Dart ライブラリを作成します。 たとえば、新しいものを作成します。DeferredBoxそのウィジェット 実行時にダウンロードできます。 このウィジェットはどんな複雑なものでもかまいませんが、 このガイドの目的上、 代わりにシンプルなボックスを作成します。 シンプルな青いボックス ウィジェットを作成するには、 作成box.dart以下の内容で:

    // box.dart
    import 'package:flutter/material.dart';
    
    /// A simple blue 30x30 box.
    class DeferredBox extends StatelessWidget {
      const DeferredBox({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Container(
          height: 30,
          width: 30,
          color: Colors.blue,
        );
      }
    }
  2. 新しい Dart ライブラリをインポートする とともにdeferredアプリ内のキーワードと 電話loadLibrary()(見るライブラリを遅延ロードする)。 次の例では、FutureBuilderを待つloadLibrary Future(作成年initState) を完了して表示します。CircularProgressIndicatorプレースホルダーとして。 ときFuture完了すると、DeferredBoxウィジェット。SomeWidgetその後、アプリで通常どおり使用できるようになり、 まで、遅延された Dart コードへのアクセスは決して試行されません。 正常にロードされました。

    import 'package:flutter/material.dart';
    import 'box.dart' deferred as box;
    
    class SomeWidget extends StatefulWidget {
      const SomeWidget({super.key});
    
      @override
      State<SomeWidget> createState() => _SomeWidgetState();
    }
    
    class _SomeWidgetState extends State<SomeWidget> {
      late Future<void> _libraryFuture;
    
      @override
      void initState() {
        _libraryFuture = box.loadLibrary();
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return FutureBuilder<void>(
          future: _libraryFuture,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.done) {
              if (snapshot.hasError) {
                return Text('Error: ${snapshot.error}');
              }
              return box.DeferredBox();
            }
            return const CircularProgressIndicator();
          },
        );
      }
    }

    loadLibrary()関数は次の値を返しますFuture<void>ライブラリ内のコードが正常に完了すると、 は使用可能ですが、それ以外の場合はエラーで完了します。 遅延ライブラリからのシンボルの使用はすべて次のようにする必要があります。 完成したものの後ろで守られているloadLibrary()電話。すべての輸入品 ライブラリのマークは次のようにマークする必要がありますdeferredそうなるために 遅延コンポーネントで使用できるように適切にコンパイルされます。 コンポーネントがすでにロードされている場合、追加の呼び出し にloadLibrary()すぐに完了します (ただし、同期的には完了しません)。 のloadLibrary()関数を早期に呼び出すこともできます プリロードをトリガーして、ロード時間をマスクします。

    遅延インポート読み込みの別の例は、次の場所にあります。Flutter Gallery の lib/deferred_widget.dart。

ステップ 3: アプリを構築する

以下を使用してくださいflutter遅延を構築するコマンド コンポーネントアプリ:

$ flutter build appbundle

このコマンドは、プロジェクトが 遅延コンポーネント アプリを構築するために適切に設定されています。 デフォルトでは、バリデーターが検出した場合、ビルドは失敗します。 問題を解決し、それらを修正するための提案された変更を案内します。

  1. flutter build appbundle指図 バリデーターを実行し、アプリのビルドを試みます。gen_snapshot分割 AOT 共有ライブラリを作成するように指示されました 別々として.soファイル。最初の実行時に、バリデーターは 問題を検出すると失敗する可能性があります。ツールが作る プロジェクトを設定し、これらの問題を解決する方法に関する推奨事項。

    バリデーターは 2 つのセクションに分かれています: prebuild そして、gen_snapshot 後の検証。これは、いずれかの理由です ロードユニットを参照する検証は実行できません それまでgen_snapshot最終セットを完成させて生成する ローディングユニットの数。

    バリデーターは、新規、変更、または削除されたものを検出します。 によって生成されたユニットをロードするgen_snapshot。 現在生成された読み込みユニットは、<projectDirectory>/deferred_components_loading_units.yamlファイル。 このファイルはソース管理にチェックインして、次のことを確認する必要があります。 他の開発者によるロードユニットへの変更をキャッチできます。

    バリデーターは、次のこともチェックします。androidディレクトリ:

    • <projectDir>/android/app/src/main/res/values/strings.xml
      キーをマッピングするすべての遅延コンポーネントのエントリ${componentName}Name${componentName}。 この文字列リソースは、AndroidManifest.xml各機能モジュールのdist:title property。 例えば:

      <?xml version="1.0" encoding="utf-8"?>
      <resources>
        ...
        <string name="boxComponentName">boxComponent</string>
      </resources>
      
    • <projectDir>/android/<componentName>
      Android 動的機能モジュール 各遅延コンポーネントが存在し、build.gradlesrc/main/AndroidManifest.xmlファイル。 これは存在をチェックするだけであり、検証はしません これらのファイルの内容。ファイルが存在しない場合は、 デフォルトの推奨されるものが生成されます。

    • <projectDir>/android/app/src/main/res/values/AndroidManifest.xml
      をエンコードするメタデータ エントリが含まれます。 ロード単位とコンポーネント名の間のマッピング ローディングユニットが関連付けられています。このマッピングは、 Dart の内部ローディング ユニット ID を変換するエンベッダー インストールする遅延コンポーネントの名前に変更します。例えば:

          ...
          <application
              android:label="MyApp"
              android:name="io.flutter.app.FlutterPlayStoreSplitApplication"
              android:icon="@mipmap/ic_launcher">
              ...
              <meta-data android:name="io.flutter.embedding.engine.deferredcomponents.DeferredComponentManager.loadingUnitMapping" android:value="2:boxComponent"/>
          </application>
          ...
      

    gen_snapshotバリデータはプリビルドされるまで実行されません バリデーターはパスします。

  2. これらの各チェックについては、 ツールは変更されたファイルまたは新しいファイルを生成します チェックに合格するために必要です。 これらのファイルは<projectDir>/build/android_deferred_components_setup_filesディレクトリ。 変更は次の方法で適用することをお勧めします。 同じファイルをコピーして上書きする プロジェクトのandroidディレクトリ。上書きする前に、 現在のプロジェクトの状態をコミットする必要があります ソース管理と推奨される変更は次のようにする必要があります。 適切であると審査されました。ツールは何も作りません あなたの変化android/ディレクトリが自動的に作成されます。

  3. 利用可能になったら ローディングユニットが生成され、ログインされます<projectDirectory>/deferred_components_loading_units.yaml、 pubspec を完全に構成することが可能ですdeferred-componentsロードユニットが 必要に応じて遅延コンポーネントに割り当てられます。 ボックスの例を続けると、生成されたdeferred_components_loading_units.yamlファイルには以下が含まれます:

    loading-units:
      - id: 2
        libraries:
          - package:MyAppName/box.Dart
    

    ローディングユニットID(この場合は「2」)が使用されます Dart によって内部的に処理されるため、無視できます。 基本ローディングユニット (ID「1」) がリストされていません 明示的に含まれていないものはすべて含まれます 別のローディングユニットにあります。

    次のものを追加できるようになりましたpubspec.yaml:

    ...
    flutter:
      ...
      deferred-components:
        - name: boxComponent
          libraries:
            - package:MyAppName/box.Dart
      ...
    

    ロードユニットを遅延コンポーネントに割り当てるには、 ロードユニット内の任意の Dart ライブラリを 機能モジュールのライブラリセクション。 次のガイドラインに留意してください。

    • ローディングユニットは含めないでください 複数のコンポーネントで。

    • からの Dart ライブラリを 1 つ含む ローディングユニットはローディング全体を示します ユニットは遅延コンポーネントに割り当てられます。

    • すべてのローディングユニットが割り当てられていません 遅延コンポーネントは基本コンポーネントに含まれます。 それは常に暗黙的に存在します。

    • 同じに割り当てられたユニットをロードする 遅延コンポーネントがダウンロード、インストールされ、 そして一緒に発送されます。

    • 基本コンポーネントは暗黙的であり、 pubspec で定義する必要はありません。

  4. 追加することでアセットを含めることもできます 遅延コンポーネント構成のアセットセクション:

      deferred-components:
        - name: boxComponent
          libraries:
            - package:MyAppName/box.Dart
          assets:
            - assets/image.jpg
            - assets/picture.png
              # wildcard directory
            - assets/gallery/
    

    アセットは複数の遅延コンポーネントに含めることができます。 ただし、両方のコンポーネントをインストールすると、アセットが複製されます。 アセットのみのコンポーネントは、 ライブラリセクション。これらのアセットのみのコンポーネントは、 とともにインストールされたDeferredComponentのユーティリティクラス ではなくサービスloadLibrary()。 Dart ライブラリはアセットと一緒にパッケージ化されているため、 Dart ライブラリがロードされている場合loadLibrary()、 コンポーネント内のアセットも同様にロードされます。 ただし、コンポーネント名とサービスユーティリティによるインストール コンポーネントにはダーツライブラリはロードされません。

    どのコンポーネントにもアセットを自由に含めることができます。 それらがインストールされロードされている限り、 通常は、最初に参照されますが、 アセットとそれらのアセットを使用する Dart コード 同じコンポーネントに梱包するのが最適です。

  5. すべての遅延コンポーネントを手動で追加する で定義したものpubspec.yamlandroid/settings.gradleファイルをインクルードとして扱います。 たとえば、遅延コンポーネントが 3 つある場合、 pubspec で定義されている名前、095af6b3-8f8e-4446-b43b-d48aebce8​​5f5、circleComponent、 とassetComponent、 確認しておいてandroid/settings.gradleには次のものが含まれます。

    include ':app', ':boxComponent', ':circleComponent', ':assetComponent'
    ...
    
  6. 手順を繰り返す3.13.6 まで (このステップ) すべてのバリデーターの推奨事項が処理され、ツールが終了するまで 追加の推奨事項なしで実行されます。

    成功すると、このコマンドは次のメッセージを出力します。app-release.aabファイルに入れるbuild/app/outputs/bundle/release

    ビルドが成功したからといって、必ずしもアプリがビルドされたことを意味するわけではありません。 意図どおりに構築されました。すべての読み込みを確実にするかどうかはあなた次第です ユニットと Dart ライブラリが意図したとおりに含まれています。 たとえば、よくある間違いは、誤ってインポートしてしまうことです。 ダーツライブラリなしdeferredキーワード、 その結果、遅延ライブラリがの一部としてコンパイルされることになります。 ベースローディングユニット。この場合、Dart ライブラリは次のようになります。 常にベースに存在するため、適切にロードされます。 ライブラリは分割されません。これは確認できます を調べることでdeferred_components_loading_units.yamlファイルに生成されたロードユニットが記述されていることを確認します 思惑通り。

    延期されたコンポーネント構成を調整する場合、 または、ローディングユニットを追加、変更、または削除する Dart の変更を行う、 バリデーターが失敗することを予期する必要があります。 手順に従ってください3.13.6 まで (このステップ) を適用して、 ビルドを続行するために推奨される変更。

アプリをローカルで実行する

アプリが正常に構築されたら、.aabファイル、 Android を使用するbundletool実行する を使用したローカルテスト--local-testing国旗。

を実行するには、.aabテストデバイス上のファイル、 から、bundletool jar 実行可能ファイルをダウンロードします。github.com/google/bundletool/releasesそして実行します:

$ java -jar bundletool.jar build-apks --bundle=<your_app_project_dir>/build/app/outputs/bundle/release/app-release.aab --output=<your_temp_dir>/app.apks --local-testing

$ java -jar bundletool.jar install-apks --apks=<your_temp_dir>/app.apks

どこ<your_app_project_dir>アプリへのパスです プロジェクトディレクトリと<your_temp_dir>一時的なものですか Bundletool の出力を保存するために使用されるディレクトリ。 これにより、開梱されます.aabファイルに.apksファイルと デバイスにインストールします。利用可能なすべての Android ダイナミック 機能はデバイスにローカルにロードされ、 遅延コンポーネントのインストールがエミュレートされます。

走る前にbuild-apksまた、 既存のアプリの .apks ファイルを削除します。

$ rm <your_temp_dir>/app.apks

Dart コードベースを変更するには、次のいずれかのインクリメントが必要です。 Android ビルド ID またはアンインストールして再インストールする Android は機能モジュールを更新しないため、アプリ 新しいバージョン番号が検出されない限り。

Google Playストアへのリリース

構築された.aabファイルを直接アップロードできます 通常どおり Play ストアにアクセスします。いつloadLibrary()と呼ばれます、 Dart AOT lib を含む必要な Android モジュールと アセットは、Flutter エンジンによってダウンロードされます。 Playストアの配信機能。