Flutter Hot Update テクノロジーの探求 | JD Cloud テクニカル チーム

1. 需要の背景:

アプリが市場にリリースされた後、ユーザーの使用に重大なバグが発生することは避けられないため、新しいバージョンのアプリをリリースすることなく、ホットアップデート技術を使用してバグを即座に修正する必要があります。ネイティブ アプリ (Android や IOS など) のホット アップデート要件は比較的成熟していますが、Flutter テクノロジー スタックには現在同様の技術ソリューションが不足しているため、Flutter R&D チームも同様のホット アップデート テクノロジーを必要としています。

2. Flutter ホット アップデート テクノロジの方向性の分析:

分析後、3 つの実現可能なソリューションがある可能性があります: 1) RN フレームワークと同様、2) ページ動的コンポーネント フレームワーク、3) Dart 仮想マシンのカスタマイズ ソリューション、3) ページ動的コンポーネント フレームワーク。

番組名 原理 アドバンテージ 欠点がある オープンソース ソリューション
RN のようなスキーム JS を使用して Flutter 構文で dart を記述し、次に JavaScript を使用して XML DSL を Flutter のアトミック ウィジェット コンポーネントに変換し、Flutter にレンダリングさせます。 iOS システムには js のサポートが組み込まれているため、更新を iOS 上で実装できます。 1) クロスランゲージ実行のため、パフォーマンスに影響があり、学習コストが高い 2) Android 側で追加の JS ライブラリを導入する必要がある Mobile QQ では MXFlutter、58.com ではフェア
ページの動的コンポーネント スキーム コンパイル中に DynamicWidget をコードに挿入/事前埋め込みし、Json データを動的に配信し、合意されたセマンティクスを JSON 内のデータと照合し、ウィジェットのコンテンツを動的に置き換えて更新を実現します。 Android/iOS の両端でのアップデートをサポート可能 1) UI の更新は比較的簡単ですが、動的なビジネス ロジックは面倒です; 2) セマンティック パーサーの開発コストは比較的高く、保守は容易ではありません; 3) フロントエンドとバックエンドのサービスとツールの完全なセットは、必要 天猫のタングラム、タオバオのDinamicXなど。
Dart 仮想マシンのカスタマイズ ソリューション Dart 仮想マシンの原理を分析して、Flutter Engine 層の Java/C++ コードを変更してホット アップデートの目標を達成します。 パフォーマンスへの影響は小さく、ダイナミクスが高く、技術的にはすべての Flutter ページ (UI、ロジック、リソース ファイルを含む) を置き換えることができます。 カスタム エンジンが使用されるため、さまざまなバージョンの Flutter エンジン コードを維持する必要があります。 オープンソースではない

他の手法にはオープンソースの事例があるため、今回は3番目の「Dart仮想マシンカスタマイズソリューション」を目標として、そのソリューションの調査と解説を行います。

3、予備知識

技術的ソリューションの理解を始める前に、対応するいくつかの技術的概念を事前に理解しておく必要があります。

3.1 フラッターコンパイルモード

Flutter の開発言語は Dart であり、そのコンパイル モードは Dart のコンパイル モードに由来しており、主に JIT (Just In Time) と AOT (Ahead Of Time) が含まれます。

コンパイルモード名 特徴 アドバンテージ 欠点がある
ジット V8 の典型的な例であるジャストインタイム コンパイル。リアルタイムで JS をコンパイルして実行できます。ソース コード文字列を入力するだけで、コードをコンパイルして実行できます。 CPU アーキテクチャに関係なくコードを動的に配信および実行でき、動的コンテンツを提供できます。 1. 文字列コードが多いと、JIT コンパイラに時間とメモリが消費されます; 2. パフォーマンスが良くありません。
AOT C/C++ の典型的な例であるプリコンパイル済み。GCC によってバイナリ コードにコンパイルされ、インストールの許可を得た後にロードして実行できます。 プリコンパイル済み、高速な読み込みと実行 1. CPU アーキテクチャはコンパイル時に区別されます; 2. 生成されたバイナリ コード パッケージは比較的大きいです; 3. バイナリ コードは実行する前に許可を取得する必要があり、iOS システム上で動的に更新できません

Flutter コンパイル モードは、デバッグ、リリース、プロファイルです。

フラッターコンパイルモード 特徴
デバッグ JIT モードに対応し、デバイスとシミュレーターをサポートします。アサーションを有効にし、迅速な開発をサポートし、HotReload をサポートします。パッケージ サイズと実行速度は最適化されません。
リリース AOT モードに対応し、実デバイスをサポートしますが、エミュレータはサポートしません。すべてのアサーション デバッグ情報を無効にし、パッケージ サイズ、起動および実行速度を最適化します。
プロフィール リリース モードと同様に、パフォーマンス分析に役立ついくつかのデバッグ機能が保持されています。

3.2 フラッターコンパイルプロダクトの分析

Flutter の iOS/Android プロジェクトは、基本的に標準の iOS/Android プロジェクトです。IOSプラットフォーム: Flutter は、BuildPhase にシェル (xcode_backend.sh) を追加することで、App.framework と Flutter.framework を生成して ios に埋め込みます。Androidプラットフォーム: Flutter は、フラッターを追加します。 jar とコンパイルされたバイナリ ファイルを gradle 経由で Android に送信します。

3.2.1 エンジン層構造の分析:

3.2.2 Android コンパイル済みプロダクトの分析

3.2.3 IOSコンパイルプロダクトの分析

4. ホットアップデート技術ソリューションの分析

4.1 ビジネスコード分析

「3.3.1」~「3.3.2」の分析によると、IOS と Android APP のビジネス コードは両方とも、kDartVmSnapshotData、kDartVmSnapshotstructs、kDartIsolateSnapshotData、kDartIsolateSnapshotstructs の 4 つのセグメントで構成されていることがわかります。ロードされたコードセグメントとデータセグメントコードを動的に置き換えて、目標を達成できます。

名前 ノート 効果 ノート
kDartIsolateSnapshotData Dart はデータ セグメントを分離します クラス情報、グローバル変数、関数ポインタなど 動的配信を許可する
kDartIsolateSnapshot手順 Dart 分離ディレクティブ セクション Dart アイソレートによって実行される AOT コードが含まれています IOS では動的配信が許可されていません
kDartVmSnapshotData vm データセグメントを分離する アイソレート間で共有される Dart ヒープの初期状態 動的配信を許可する
kDartVmSnapshot手順 vm 命令セグメントを分離 VM 内のすべての Dart アイソレート間で共有される共通プログラムの AOT 命令が含まれています IOS では動的配信が許可されていません

注: isolate、snapshot、vm isolate の意味は次のように説明されています。

名前 意味
隔離する Dart は単一のスレッドであり、isolate はスレッドに似ており、Dart のスレッドとして理解できます。isolate と thread の違い: メモリはスレッド間で共有されますが、isolate と isolate の間ではメモリは共有されません。ロック競合の問題はありません。2 つの Isolate は完全に独立した実行ラインであり、各 Isolate には独自のイベント ループがあります。これらはメッセージを送信することによってのみ相互に通信できるため、リソースのオーバーヘッドはスレッドよりも低くなります。
スナップショット クラス情報、グローバル変数、関数命令などをシリアル化してディスクに直接保存することをスナップショット(スナップショット)と呼びます。
vm の分離 同じプロセス内に多数のアイソレートを含めることができますが、2 つのアイソレートのヒープ領域を共有することはできないため、VM アイソレートの公式設計、つまり kDartVmSnapshot が複数のアイソレート間の相互作用に使用されます。

4.2 業務コードの読み込み解析(ランタイム)

4.1 の分析アイデアによれば、まず Flutter 実行時のコード読み込みの完全なプロセスを理解する必要があり、分析プロセスは次のとおりです。

1) Android-APP ビジネスコード読み込みプロセス:

2) IOS-APP ビジネスコード読み込みプロセス:

4.3 業務コードのコンパイルと生成(コンパイル時)

上記の分析によると、Flutter ビジネス コードのデータ構造と、それを実行時にロードする方法がわかっているため、コンパイル時に変更を加えるだけで、必要なコード セグメントとデータ セグメント ファイルを生成できます。これは、実行時に独自のビルド アーティファクトをロードすることで実現されます。

1) 以下は、IOS を使用して独自のビジネス コードを構築するプロセスの詳細な分析です。

** 解析可能な構築プロセスが完成しており、基本的なプロセスは「Dartコード(ビジネスコード)」→(Dartコンパイラgen_snapshot.cc経由)、snapshot_assemble.Sのアセンブリファイル生成→( xcrun ツール) を使用して、snapshot_assemble.o obj ファイルを生成します -> App.Framework が生成されます (xcun clang ツールチェーン経由)。

2) Android の製品ビルド プロセスは IOS と似ています。Android には他のより単純なソリューションがあるため、詳細な構築プロセスの分析は省略します。おおよそ次のとおりです。

4.4 ホットアップデートを実現するソリューションの検討

上記の技術分析結果によると、独自のコード セグメント ファイルとデータ セグメント ファイルをすでに個別に生成できます。仮想マシンの基盤となるコードを変更することで、仮想マシンを動的にロードして実行することもできます。ただし、IOS システムの現在の基盤システムは、読み取りおよび書き込み可能なコード セグメント データをメモリに動的にロードできないため、克服する必要のある技術的な問題がまだあります。ただし、Android 側には解決するためのより簡単な方法があるため、以下では Android 側を例として使用し、アイデアの分析に焦点を当てます。大まかに次の図に示すとおりです。

上の図からわかるように、Android 側のホット リペアの中心的な手順は次のとおりです。

1. Flutter Engine コードを変更して、プライベート ディレクトリ (data/data/files) などの指定されたパスに libapp.so と flutter_aasets をロードします。

2. APK をコンパイルするときに、Gradle Transform プラグインを使用して、Flutter SDK のエンジン バージョンに従って公式の Flutter エンジンを動的に置き換え、最後に変更したエンジンを APK に書き込みます。

3. パッチ パッケージを生成します。BSdiff アルゴリズムを使用して古い APK ファイルと新しい APK ファイルを比較し、パッチ パッチ パッケージを生成します。

4. APP の起動時にバックエンド インターフェイスにアクセスし、パラメーター (アプリのバージョン番号、パッチ パッケージのバージョン番号、md5、flutter SDK バージョン番号、エンジン バージョン番号) に従ってパッチ パッケージをプルします。

5. 複合パッチ パッケージ: md5、アプリのバージョン番号、パッチのバージョン番号、インストール時間を確認します。

6. Flutter エンジンをカスタマイズして、指定されたパスに libapp.so および flutter_assets リソース ファイルをロードします。

 

著者: JD Technology Liu Zhenzhong、Zhou Zhi

コンテンツソース: JD Cloud 開発者コミュニティ

{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/u/4090830/blog/9092965