読者です 読者をやめる 読者になる 読者になる

そーす

福岡在住のプログラマ

ReactNativeのソースを読んで見る(Android編①)

AndroidStudio Java Javascript React ReactNative

*Android編①って書いてるけどAndroid編②があるとかiOS編があるとかは未定です

ReactNativeの「Native」の部分がどう動いてるのか気になったのでソース見てみました。 細かい所まで見てないですし、間違った認識かもしれませんのであしからず。

エントリポイントはMainActivity

AndroidManifestにはMainActivityとDevSettingsActivityでaction.MainがMainActivityでここからアプリがスタートするようです。 DevSettingsActivityはデバッグ用のメニュー(ReloadやLiveReloadなどのメニュー)を表示するためのアクティビティのようです。

MainActivity

ReactActivityというAbstractClassを継承したクラスで自動でgetMainComponentNameがオーバライドされてプロジェクト名を返すようになっています。

ReactActivity

Activityを継承しDefaultHardwareBackBtnHandler, PermissionAwareActivityを実装したクラスです。 基本的にはActivityでしか受け取れないイベント(ライフサイクルやonActivityResultなど)が起きたときにReactActivityDelegateに伝播するクラスです。DefaultHardwareBackBtnHandlerはJSModuleから呼び出されonBackPressedを実行するinvokeDefaultOnBackPressedのみをインターフェースとして持っており、PermissionAwareActivityはActivityのパーミッション関連のメソッドと全く同じメソッドが定義されたインターフェースです。 ちなみにデフォルトで生成されるMainActivityはandroid.app.Activityを継承していますが android.support.v4.app.FragmentActivityを継承したReactFragmentActivityも用意してあります。サポートパッケージを使う場合はこちらに変更するようです。

ReactActivityDelegate

このクラスも基本的にはReactActivityから伝播されたイベントをReactInstanceManagerに伝播しています。 デバッグ時のメニュー表示に必要なパーミッションの処理もこのクラスで処理されています。 onCreateでloadAppメソッドでReactRootViewのインスタンスが生成され、startReactApplicationを実行した後setContentViewされます。

ReactRootView

このクラスはSizeMonitoringFrameLayoutを継承しRootViewを実装しています。 SizeMonitoringFrameLayoutはonSizeChanged発生時にリスナを発火してくれるだけのFrameLayoutのサブクラスです。 RootViewは子ViewにMotionイベントが発生した時に呼ばれるonChildStartedNativeGestureだけを持つインターフェースです。 ReactRootViewは基本的にタッチイベントやViewの表示領域の変更(回転やキーボードの有無)をJS側へ通知する処理をしています。 onMeasureが呼ばれ描画領域が確定するとattachToReactInstanceManagerが呼ばれReactInstanceManagerのインスタンスメソッドattachMeasuredRootViewが呼ばれReactRootViewが渡されます。 デフォルトではReactInstanceManagerはXReactInstanceManagerImplのインスタンスがセットされます。

XReactInstanceManagerImpl

このクラスはまだ全然理解出来てません。 setupReactContextでReactRootViewの初期化を行っています。 XReactInstanceManagerImplはReactRootViewの配列をフィールドに持っており、個々の初期化はattachMeasuredRootViewToInstanceで行われています。 attachMeasuredRootViewToInstanceはReactRootViewとCatalystInstanceを引数に持ち、CatalystInstanceクラスはJS<->JavaAPI呼び出しをする環境を提供してくれるらしいです。

UIManagerModule

catalystInstance.getNativeModule(UIManagerModule.class)でUIManagerModuleのインスタンスを取得してます。このクラスはReactContextBaseJavaModuleを継承しており、これはJS側からJavaのコードを呼ぶために必要なものです。自分でJavaからAPIを呼びたい時はこのクラスのサブクラスをつくります。 UIManagerModuleはJSのComponentからイベントを受け取り、フィールドのUIImplementationのインスタンスに伝播します。 UIManagerModuleのaddMeasuredRootViewメソッドでは引数のReactRootViewをフィールドのUIImplementationに登録しています。

UIImplementation

最終的にコイツがReactRootViewを持ち、JSのComponentからイベント受け取って描画すると思われる(この実装は今後読む