React Nativeの起動プロセスの詳細分析

React Nativeの起動プロセスの詳細分析

はじめに: この記事ではreact-native-cliで作成したサンプル プロジェクト (Android 部分) を例に、React Native の起動プロセスを分析します。

プロジェクト作成の手順については公式ウェブサイトを参照してください。この記事で分析したReact Nativeバージョンはv0.64.2です。

上記のプロジェクトは Android アプリケーションであることがわかっています。 android/ディレクトリのソース コード ファイルを開くと、まずMainApplication.javaMainActivity.javaという 2 つの Java ファイルが作成され、それぞれアプリケーションとメイン アクティビティが定義されていることがわかります。

Android アプリケーションの起動プロセスは次のとおりです。最初のactivityが開始される前に、グローバルに一意のApplicationオブジェクトが作成されます。そこでまずMainApplicationを分析します

メインアプリケーション

パブリッククラス MainApplication は Application を拡張し、ReactApplication を実装します {
  プライベートファイナルReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @オーバーライド
        パブリックブール値 getUseDeveloperSupport() {
          BuildConfig.DEBUG を返します。
        }
        @オーバーライド
        保護されたリスト<ReactPackage> getPackages() {
          @SuppressWarnings("不要なローカル変数")
          リスト<ReactPackage> パッケージ = 新しい PackageList(this).getPackages();
          // パッケージに対するその他の操作はパッケージを返します。
        }
        @オーバーライド
        保護された文字列 getJSMainModuleName() {
          「インデックス」を返します。
        }
  }
  @オーバーライド
  パブリックReactNativeHost getReactNativeHost() {
    mReactNativeHost を返します。
  }
  @オーバーライド
  パブリックvoid onCreate() {
    スーパーのonCreate();
    SoLoader.init(this, /* ネイティブ exopackage */ false);
    フリッパーを初期化します(これ、getReactNativeHost().getReactInstanceManager());
  }

MainApplication Application クラスを継承し、 ReactApplicationインターフェースを実装します。やるべきことは次のとおりです:

1. メンバー変数ReactNativeHostのインスタンスを作成し、作成プロセス中に ReactNativeHost クラス メソッドをオーバーライドして、次のようないくつかの構成を挿入します。

  1. getUseDeveloperSupport: デバッグを有効にするかどうかを設定します
  2. getPackages: ロードするモジュールを構成する
  3. getJSMainModuleName: jsモジュールのエントリファイル名を設定します

2. onCreate で:

  1. Soloaer ライブラリを呼び出します。 Soloaderは Facebook がリリースした s​​o ファイル読み込みライブラリです。so ファイルの依存関係を処理できます。react-native では、フレームワーク関連の so ファイルはすべて SoLoader を通じて読み込まれます。
  2. ReactInstanceManagerを介して Flipper を初期化します。 Flipper 、iOS、Android、React Native アプリケーションをデバッグするために Facebook がリリースしたツールです。

ReactNativeHostReactInstanceManagerの簡単な紹介です

リアクトネイティブホスト

ReactNativeHostは抽象クラスであり、開発者はそのメソッドをオーバーライドできます。その主な機能は、アプリケーションでいくつかの割り当て操作を指定して、 ReactInstanceManagerのインスタンスを取得することです。したがって、 ReactNativeHostReactInstanceManagerインスタンスにユーザー定義のパラメータを割り当てるための中継ステーションとして使用できます。コアメソッドはgetReactInstanceManagerです。詳細な分析については以下を参照してください。

Reactインスタンスマネージャー

このクラスはコアクラスであり、主に JS の読み込みの管理、ライフサイクルの維持、JS と C++ 間の相互作用の管理などを担当します。 ReactInstanceManager 、JS と C++ 間の転送ブリッジとして理解できます。

メインアクティビティ

次に、 MainActivity.javaを見てみましょう。

パブリッククラスMainActivityはReactActivityを拡張します{
  @オーバーライド
  保護された文字列 getMainComponentName() {
    「myProject」を返します。
  }
}

MainActivityクラスでは getMainComponentName メソッドのみがオーバーライドされます。このクラスはReactActivityから継承します。そのReactActivityを見てみましょう。

パブリック抽象クラス ReactActivity は AppCompatActivity を拡張します
    DefaultHardwareBackBtnHandler、PermissionAwareActivityを実装します。
  プライベート最終 ReactActivityDelegate mDelegate;
  @オーバーライド
  保護されたvoid onCreate(バンドルsavedInstanceState) {
    super.onCreate(保存されたインスタンス状態);
    mDelegate.onCreate(保存されたインスタンス状態);
  }

ReactActivity onCreateライフサイクルの処理をReactActivityDelegateに完全に委任します。 ReactActivityDelegateonCreateを見てみましょう。

保護されたvoid onCreate(バンドルsavedInstanceState) {
  文字列 mainComponentName = getMainComponentName();
  mReactデリゲート =
      新しいReactDelegate(
          getPlainActivity()、getReactNativeHost()、mainComponentName、getLaunchOptions()) {
        @オーバーライド
        保護されたReactRootView createRootView() {
          ReactActivityDelegate.this.createRootView() を返します。
        }
      };
    mMainComponentName != null の場合 {
      loadApp(メインコンポーネント名);
    }
  }

ここで、ReactDelegate インスタンスが最初に作成されます。次に、 loadAppメソッドを見てみましょう。

保護されたvoid loadApp(String appKey) {
  mReactDelegate.loadApp(appKey);
  getPlainActivity().setContentView(mReactDelegate.getReactRootView());
}

ここから、 ReactDelegateインスタンスのloadAppメソッドに進みます。

パブリック void loadApp(String appKey) {
  mReactRootView が null の場合
    throw new IllegalStateException("アプリがすでに実行中なので、loadApp を実行できません。");
  }
  mReactRootView = createRootView();
  mReactRootView.startReactApplication() を実行します。
      getReactNativeHost().getReactInstanceManager(), appKey, mLaunchOptions);
}

ここでは、rootView ( createRootView ) の作成、ReactInstanceManager ( getReactInstanceManager ) の作成、ReactApplication ( startReactApplication ) の作成という 3 つの処理が行われます。

ルートビューの作成

まず、rootView とは何かを見てみましょう。

パブリッククラス ReactRootView は FrameLayout を拡張し、RootView、ReactRoot を実装します { /* ... */

ReactRootView はFrameLayoutを継承し、 RootViewおよびReactRootインターフェースを実装します。 FrameLayoutは、Android のよりシンプルなレイアウトの 1 つです。インターフェース全体が空白の予備領域として扱われ、すべての要素が左上隅を揃えて積み重ねられます。 ReactRootView はFrameLayoutを継承しており、これも単純なレイアウトとして存在し、 UI 的繪制渲染その上で行われることを示しています。

getReactInstanceManager

ReactInstanceManager 、JS の読み込み、C++ と JS の相互作用、初期化パラメータなどを管理するコア クラスです。最後に、 ReactNativeHostクラスのcreateReactInstanceManagerメソッドが呼び出されます。

保護されたReactInstanceManager createReactInstanceManager() {
  ReactInstanceManagerBuilder ビルダー = /* ... */

  (ReactPackage reactPackage : getPackages()) の場合 {
    ビルダーにパッケージを追加します。
  }

  文字列 jsBundleFile = getJSBundleFile();
  jsBundleFile != null の場合 {
    ビルダーでJSBundleFileを設定します(jsBundleFile);
  } それ以外 {
    バンドルアセット名をアサーションにセットします。
  }
  
  React インスタンスマネージャー reactInstanceManager = builder.build();
  reactInstanceManager を返します。
}

何が起こっているのか、以下に示します。

  • ReactInstanceManagerBuilderインスタンスを作成します。ここでは、 ReactInstanceManagerインスタンスを構築するためにビルダー パターンが使用されているため、最初にコンストラクターを設定するためにパラメーターが渡されます。
  • ReactNativeHostに登録されているすべてのpackagesReactInstanceManagerBuilderインスタンスに追加します。
  • getJSBundleFileが空でない場合は対応するファイルをロードし、そうでない場合はデフォルトのjsBundleFileをロードします。
  • builder.buildメソッドを呼び出します。実際にビルダーを通じてReactInstanceManagerインスタンスを構築する

Reactアプリケーションを起動する

  パブリック void startReactApplication(/* */) {
    // ...
    試す {
      // ...
      mReactInstanceManager.createReactContextInBackground();
    ついに
      // ...
    }
  }

最後に、 ReactInstanceManagercreateReactContextInBackgroundメソッド内で実行が行われます。最終的に、呼び出しチェーンは次のようになります: recreateReactContextInBackgroundInner() -> recreateReactContextInBackgroundFromBundleLoader() -> recreateReactContextInBackground() -> runCreateReactContextOnNewThread()

runCreateReactContextOnNewThread主に次の 2 つのことを行います。

  1. 新しいスレッドを作成し、新しいスレッドでcreateReactContextを通じてReactContextコンテキストを作成します。
  2. コンテキスト環境はsetupReactContextを通じて設定され、最後にAppRegistry.jsが呼び出されてアプリが起動します。

詳細な分析については、別の記事「React Native startReactApplication プロセス分析」に掲載します。

要約する

この記事をまとめると、 react-native-cliで作成したサンプルプロジェクト(Android 部分)を例に、 MainApplicationMainActivity 2 つのクラスの実行フローを辿り、主要なロジックを把握し、最後にReact Nativeの起動からユーザーjsファイルの実行までのプロセスを整理しました。以下が見られます:

MainApplicationの主な機能は、ユーザーの設定を渡し、 soライブラリとアプリケーションdebugツールを初期化することです。

MainActivityの主な機能は次のとおりです。

  1. アプリケーションのrootViewレイアウト コンテナーを作成します。
  2. JS の読み込み、C++ と JS の相互作用、初期化パラメータなどを管理するためのReactInstanceManagerコア クラスを作成します。
  3. ReactContextコンテキストはstartReactApplicationを通じて作成され、最後にAppRegistry.jsが呼び出されてアプリが起動します。

React Native の起動プロセスの簡単な分析に関するこの記事はこれで終わりです。React Native の起動に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • React NativeのScrollViewプルダウンリフレッシュ効果
  • React NativeのstartReactApplicationメソッドの簡単な分析
  • React Nativeのカスタムルーティング管理に関する深い理解
  • React NativeプロジェクトでLottieアニメーションを使用する方法

<<:  Mysql一時テーブルの原理と作成方法の分析

>>:  VMWARE で Centos8 仮想マシンをコピーすることによって発生する IP 損失の問題の解決策

推薦する

Mybatisの各SQL文の実行時間の統計

背景最近、面接でデータベース トランザクションについてよく質問されます。通常は、@Transacti...

Webフロントエンド開発エンジニアが習得すべきコアスキル

Web フロントエンド開発に含まれる内容は、主に W3C 標準の構造、動作、パフォーマンスです。では...

ES6 における Object.assign() の使い方の詳細な説明

目次2. 目的2.1 オブジェクトにプロパティを追加する2.3 オブジェクトの複製2.4 複数のオブ...

DD DT DLタグの使用例

通常は <ul><li> タグを使用しますが、dd タグと dt タグも便利...

wavesurfer.js によるオーディオ波形描画の実装

1. レンダリングを見る進むを選択: 後方を選択: コードは次のとおりです(例): <テンプレ...

node-media-serverを使用してシンプルなストリーミングメディアサーバーを構築する

node-media-server を使用するプロセスの一部を記録します。この記事の環境はWindo...

モバイルデバイスで 1 ピクセルの境界線の問題を解決するいくつかの方法 (5 つの方法)

この記事では、モバイルデバイス上の 1 ピクセルの境界線の問題を解決する 5 つの方法を紹介します。...

MySQL で時刻と日付の型を保存する際の選択問題を分析する

一般的なアプリケーションでは、timestamp、datetime、int 型を使用して時間形式を保...

Reactはダブルスライダークロススライドを実装します

この記事では、Reactでダブルスライダークロススライドを実装するための具体的なコードを参考までに共...

プロジェクトを素早く構築するためのvite+vue3.0+ts+element-plusの実装

目次バイト機能使用環境プロジェクトを構築する構成vite.config.ts tsconfig.js...

Navicatを使ってMySQLを操作する方法

目次序文: 1. Navicatの紹介2. シンプルなチュートリアルの共有接続管理ライブラリテーブル...

ApplicationHost.config (IIS ストレージ構成領域ファイル) の概要

新しく作成された Web サイトの場合は、ASP.NET MVC5 を例に挙げます。セッションを処理...

MYSQL ストアドプロシージャと関数の簡単な記述

ストアドプロシージャとは簡単に言えば、これは強力で、JAVA 言語のメソッドに似た比較的複雑な論理関...

XHTML 入門チュートリアル: Web ページのヘッダーと DTD

ヘッドと DTD はページには表示されませんが、Web ページの重要な要素です。 なぜ失敗したのでし...

MySQL スロークエリログの役割と公開

序文MySQL スロー クエリ ログは、MySQL が提供するログ レコードの一種です。これは、応答...