当前位置: 首页 > news >正文

React Native 启动流程 (Android版)

React Native 启动流程 (Android版)

我们从骨架项目MainActivity说起.其继承实现了ReactActivity.
进入MainActivity,先反射MainActivity执行其父类ReactActivity和自己的构造方法。

/** Base Activity for React Native applications. */
public abstract class ReactActivity extends AppCompatActivityimplements DefaultHardwareBackBtnHandler, PermissionAwareActivity {private final ReactActivityDelegate mDelegate;protected ReactActivity() {mDelegate = createReactActivityDelegate();}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mDelegate.onCreate(savedInstanceState);}

然后执行onCreate方法。

class MainActivity : ReactActivity() {/*** Returns the name of the main component registered from JavaScript. This is used to schedule* rendering of the component.*/override fun getMainComponentName(): String = "HelloAndroid"/*** Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]* which allows you to enable New Architecture with a single boolean flags [fabricEnabled]*/override fun createReactActivityDelegate(): ReactActivityDelegate =DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)}
}

然后调用DefaultReactActivityDelegate实际上是其父类ReactActivityDelegateonCreate的方法。

public open class DefaultReactActivityDelegate(activity: ReactActivity,mainComponentName: String,private val fabricEnabled: Boolean = false,
) : ReactActivityDelegate(activity, mainComponentName) {@Deprecated(message ="Creating DefaultReactActivityDelegate with both fabricEnabled and " +"concurrentReactEnabled is deprecated. Please pass only one boolean value that will" +" be used for both flags",level = DeprecationLevel.WARNING,replaceWith =ReplaceWith("DefaultReactActivityDelegate(activity, mainComponentName, fabricEnabled)"))public constructor(activity: ReactActivity,mainComponentName: String,fabricEnabled: Boolean,@Suppress("UNUSED_PARAMETER") concurrentReactEnabled: Boolean,) : this(activity, mainComponentName, fabricEnabled)override fun isFabricEnabled(): Boolean = fabricEnabled
}

然后调用ReactActivityDelegate的构造方法

public class ReactActivityDelegate {public ReactActivityDelegate(@Nullable ReactActivity activity, @Nullable String mainComponentName) {mActivity = activity;mMainComponentName = mainComponentName;}@DeprecatedInNewArchitecture(message = "Use getReactHost()")protected ReactNativeHost getReactNativeHost() {return ((ReactApplication) getPlainActivity().getApplication()).getReactNativeHost();}public @Nullable ReactHost getReactHost() {return ((ReactApplication) getPlainActivity().getApplication()).getReactHost();}public void onCreate(Bundle savedInstanceState) {Systrace.traceSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,"ReactActivityDelegate.onCreate::init",() -> {String mainComponentName = getMainComponentName(); // 项目的index.js注册的名字,我这边叫HelloWorldfinal Bundle launchOptions = composeLaunchOptions();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && isWideColorGamutEnabled()) {mActivity.getWindow().setColorMode(ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT);}if (ReactNativeFeatureFlags.enableBridgelessArchitecture()) { // 1 true为新架构,false为就架构mReactDelegate =new ReactDelegate(getPlainActivity(), getReactHost(), mainComponentName, launchOptions);} else { // 2mReactDelegate =new ReactDelegate(getPlainActivity(), // activitygetReactNativeHost(), // Application的reactNativeHostmainComponentName,  // HelloWorldlaunchOptions,isFabricEnabled()) { // fabricEnabled = true@Overrideprotected ReactRootView createRootView() {ReactRootView rootView = ReactActivityDelegate.this.createRootView();if (rootView == null) {rootView = super.createRootView(); // 1}return rootView;}};}if (mainComponentName != null) {loadApp(mainComponentName); // 2}});}protected void loadApp(String appKey) {mReactDelegate.loadApp(appKey);getPlainActivity().setContentView(mReactDelegate.getReactRootView());}
}
1处创建了`ReactDelegate`的匿名对象,并实现了`createRootView`方法,且调用了`ReactDelegate`的`createRootView`方法。

旧架构

我们来看旧架构。

public class ReactDelegate {private final Activity mActivity;@Nullable private ReactRootView mReactRootView;@Nullable private final String mMainComponentName;@Nullable private Bundle mLaunchOptions;@Nullable private DoubleTapReloadRecognizer mDoubleTapReloadRecognizer;@Nullable private ReactNativeHost mReactNativeHost;@Nullable private ReactHost mReactHost;@Nullable private ReactSurface mReactSurface; // 新架构才需要关心private boolean mFabricEnabled = ReactNativeFeatureFlags.enableFabricRenderer();public ReactDelegate(Activity activity,ReactNativeHost reactNativeHost,@Nullable String appKey,@Nullable Bundle launchOptions,boolean fabricEnabled) {mFabricEnabled = fabricEnabled;mActivity = activity;mMainComponentName = appKey;mLaunchOptions = launchOptions;mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();mReactNativeHost = reactNativeHost;}protected ReactRootView createRootView() {ReactRootView reactRootView = new ReactRootView(mActivity);reactRootView.setIsFabric(isFabricEnabled());return reactRootView;}/*** Start the React surface for the given app key.** @param appKey The ID of the app to load into the surface.*/public void loadApp(String appKey) {// With Bridgeless enabled, create and start the surfaceif (ReactNativeFeatureFlags.enableBridgelessArchitecture()) {if (mReactSurface == null) {mReactSurface = mReactHost.createSurface(mActivity, appKey, mLaunchOptions);}mReactSurface.start();} else { // 1if (mReactRootView != null) {throw new IllegalStateException("Cannot loadApp while app is already running.");}mReactRootView = createRootView();mReactRootView.startReactApplication( // 2getReactNativeHost().getReactInstanceManager(), appKey, mLaunchOptions);}}}

createRootView创建了一个ReactRootView对象,ReactActivityDelegate实例对象调用了loadApp然后将ReactRootView设置给了Activity.
2处真正启动了RN运行时环境,
看下ReactNativeHost,这玩意过时了可以使用ReactHost替代,下篇文章分析它。

/*** Simple class that holds an instance of {@link ReactInstanceManager}. This can be used in your* {@link Application class} (see {@link ReactApplication}), or as a static field.*/
@DeprecatedInNewArchitecture(message ="This class will be replaced by com.facebook.react.ReactHost in the new architecture of"+ " React Native.")
public abstract class ReactNativeHost {private final Application mApplication;private @Nullable ReactInstanceManager mReactInstanceManager;protected ReactNativeHost(Application application) {mApplication = application;}/*** Get the current {@link ReactInstanceManager} instance, or create one.** <p>NOTE: Care must be taken when storing this reference outside of the ReactNativeHost* lifecycle. The ReactInstanceManager will be invalidated during {@link #clear()}, and may not be* used again afterwards.*/public synchronized ReactInstanceManager getReactInstanceManager() {if (mReactInstanceManager == null) {ReactMarker.logMarker(ReactMarkerConstants.INIT_REACT_RUNTIME_START);ReactMarker.logMarker(ReactMarkerConstants.GET_REACT_INSTANCE_MANAGER_START);mReactInstanceManager = createReactInstanceManager();ReactMarker.logMarker(ReactMarkerConstants.GET_REACT_INSTANCE_MANAGER_END);}return mReactInstanceManager;}protected ReactInstanceManager createReactInstanceManager() {ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_START);ReactInstanceManagerBuilder builder = getBaseReactInstanceManagerBuilder();ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_END);return builder.build();}protected ReactInstanceManagerBuilder getBaseReactInstanceManagerBuilder() {ReactInstanceManagerBuilder builder =ReactInstanceManager.builder().setApplication(mApplication).setJSMainModulePath(getJSMainModuleName()).setUseDeveloperSupport(getUseDeveloperSupport()).setDevSupportManagerFactory(getDevSupportManagerFactory()).setDevLoadingViewManager(getDevLoadingViewManager()).setRequireActivity(getShouldRequireActivity()).setSurfaceDelegateFactory(getSurfaceDelegateFactory()).setJSExceptionHandler(getJSExceptionHandler()).setLazyViewManagersEnabled(getLazyViewManagersEnabled()).setRedBoxHandler(getRedBoxHandler()).setJavaScriptExecutorFactory(getJavaScriptExecutorFactory()).setUIManagerProvider(getUIManagerProvider()).setInitialLifecycleState(LifecycleState.BEFORE_CREATE).setReactPackageTurboModuleManagerDelegateBuilder(getReactPackageTurboModuleManagerDelegateBuilder()).setJSEngineResolutionAlgorithm(getJSEngineResolutionAlgorithm()).setChoreographerProvider(getChoreographerProvider()).setPausedInDebuggerOverlayManager(getPausedInDebuggerOverlayManager());for (ReactPackage reactPackage : getPackages()) {builder.addPackage(reactPackage);}String jsBundleFile = getJSBundleFile();if (jsBundleFile != null) {builder.setJSBundleFile(jsBundleFile);} else {builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName()));}return builder;}

可以看到getJSBundleFile优先于getBundleAssetName.

看下 mReactRootView.startReactApplication

react-native/packages/react-native/ReactAndroid/src/main/java/com/facebook/react /ReactRootView.java

 public void startReactApplication(ReactInstanceManager reactInstanceManager, String moduleName) {startReactApplication(reactInstanceManager, moduleName, null);}/*** Schedule rendering of the react component rendered by the JS application from the given JS* module (@{param moduleName}) using provided {@param reactInstanceManager} to attach to the JS* context of that manager. Extra parameter {@param initialProperties} can be used to pass initial* properties for the react component.*/@ThreadConfined(UI)public void startReactApplication(ReactInstanceManager reactInstanceManager,String moduleName,@Nullable Bundle initialProperties) {Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "startReactApplication");try {UiThreadUtil.assertOnUiThread();// TODO(6788889): Use POJO instead of bundle here, apparently we can't just use WritableMap// here as it may be deallocated in native after passing via JNI bridge, but we want to reuse// it in the case of re-creating the catalyst instanceAssertions.assertCondition(mReactInstanceManager == null,"This root view has already been attached to a catalyst instance manager");mReactInstanceManager = reactInstanceManager;mJSModuleName = moduleName;mAppProperties = initialProperties;mReactInstanceManager.createReactContextInBackground(); // 1// if in this experiment, we initialize the root earlier in startReactApplication// instead of waiting for the initial measureif (ReactNativeFeatureFlags.enableEagerRootViewAttachment()) {if (!mWasMeasured) {// Ideally, those values will be used by default, but we only update them here to scope// this change to `enableEagerRootViewAttachment` experiment.setSurfaceConstraintsToScreenSize();}attachToReactInstanceManager();}} finally {Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);}}

查看1处的源码

@ThreadSafe
@StableReactNativeAPI
public class ReactInstanceManager {private static final String TAG = ReactInstanceManager.class.getSimpleName();@ThreadConfined(UI)public void createReactContextInBackground() {FLog.d(TAG, "ReactInstanceManager.createReactContextInBackground()");UiThreadUtil.assertOnUiThread(); // Assert before setting mHasStartedCreatingInitialContext = trueif (!mHasStartedCreatingInitialContext) {mHasStartedCreatingInitialContext = true;recreateReactContextInBackgroundInner(); // 1}}/*** Recreate the react application and context. This should be called if configuration has changed* or the developer has requested the app to be reloaded. It should only be called after an* initial call to createReactContextInBackground.** <p>Called from UI thread.*/@ThreadConfined(UI)public void recreateReactContextInBackground() {Assertions.assertCondition(mHasStartedCreatingInitialContext,"recreateReactContextInBackground should only be called after the initial "+ "createReactContextInBackground call.");recreateReactContextInBackgroundInner();}@ThreadConfined(UI)private void recreateReactContextInBackgroundInner() {FLog.d(TAG, "ReactInstanceManager.recreateReactContextInBackgroundInner()");PrinterHolder.getPrinter().logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: recreateReactContextInBackground");UiThreadUtil.assertOnUiThread();if (mUseDeveloperSupport && mJSMainModulePath != null) { // debug模式final DeveloperSettings devSettings = mDevSupportManager.getDevSettings();if (!Systrace.isTracing(TRACE_TAG_REACT_APPS | TRACE_TAG_REACT_JS_VM_CALLS)) {if (mBundleLoader == null) {mDevSupportManager.handleReloadJS();} else {mDevSupportManager.isPackagerRunning(new PackagerStatusCallback() {@Overridepublic void onPackagerStatusFetched(final boolean packagerIsRunning) {UiThreadUtil.runOnUiThread(() -> {// ReactInstanceManager is no longer valid, ignore callbackif (mInstanceManagerInvalidated) {return;}if (packagerIsRunning) {mDevSupportManager.handleReloadJS();} else if (mDevSupportManager.hasUpToDateJSBundleInCache()&& !devSettings.isRemoteJSDebugEnabled()&& !mUseFallbackBundle) {// If there is a up-to-date bundle downloaded from server,// with remote JS debugging disabled, always use that.onJSBundleLoadedFromServer();} else {// If dev server is down, disable the remote JS debugging.devSettings.setRemoteJSDebugEnabled(false);recreateReactContextInBackgroundFromBundleLoader();}});}});}return;}}recreateReactContextInBackgroundFromBundleLoader(); // 2}@ThreadConfined(UI)private void recreateReactContextInBackgroundFromBundleLoader() {FLog.d(TAG, "ReactInstanceManager.recreateReactContextInBackgroundFromBundleLoader()");PrinterHolder.getPrinter().logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: load from BundleLoader");recreateReactContextInBackground(mJavaScriptExecutorFactory, mBundleLoader); // 3}@ThreadConfined(UI)private void recreateReactContextInBackground(JavaScriptExecutorFactory jsExecutorFactory, JSBundleLoader jsBundleLoader) {FLog.d(ReactConstants.TAG, "ReactInstanceManager.recreateReactContextInBackground()");UiThreadUtil.assertOnUiThread();final ReactContextInitParams initParams =new ReactContextInitParams(jsExecutorFactory, jsBundleLoader);if (mCreateReactContextThread == null) {runCreateReactContextOnNewThread(initParams); // 4} else {mPendingReactContextInitParams = initParams;}}@ThreadConfined("UI")private void runCreateReactContextOnNewThread(ReactContextInitParams initParams) {FLog.d("ReactNative", "ReactInstanceManager.runCreateReactContextOnNewThread()");UiThreadUtil.assertOnUiThread();Assertions.assertCondition(!this.mInstanceManagerInvalidated, "Cannot create a new React context on an invalidated ReactInstanceManager");ReactMarker.logMarker(ReactMarkerConstants.REACT_BRIDGE_LOADING_START);synchronized(this.mAttachedReactRoots) {synchronized(this.mReactContextLock) {if (this.mCurrentReactContext != null) {this.tearDownReactContext(this.mCurrentReactContext); // 旧 Context 清理this.mCurrentReactContext = null;}}}this.mCreateReactContextThread = new Thread((ThreadGroup)null, () -> {ReactMarker.logMarker(ReactMarkerConstants.REACT_CONTEXT_THREAD_END);synchronized(this.mHasStartedDestroying) {while(this.mHasStartedDestroying) {try {this.mHasStartedDestroying.wait();} catch (InterruptedException var7) {}}}this.mHasStartedCreatingInitialContext = true;ReactApplicationContext reactApplicationContext;try {Process.setThreadPriority(-4);ReactMarker.logMarker(ReactMarkerConstants.VM_INIT);reactApplicationContext = this.createReactContext(initParams.getJsExecutorFactory().create(), initParams.getJsBundleLoader()); // 1} catch (Exception e) {this.mHasStartedCreatingInitialContext = false;this.mCreateReactContextThread = null;this.mDevSupportManager.handleException(e);return;}try {this.mCreateReactContextThread = null;ReactMarker.logMarker(ReactMarkerConstants.PRE_SETUP_REACT_CONTEXT_START);Runnable maybeRecreateReactContextRunnable = () -> {if (this.mPendingReactContextInitParams != null) {this.runCreateReactContextOnNewThread(this.mPendingReactContextInitParams); // 2this.mPendingReactContextInitParams = null;}};Runnable setupReactContextRunnable = () -> {try {this.setupReactContext(reactApplicationContext); // 3} catch (Exception e) {this.mDevSupportManager.handleException(e);}};reactApplicationContext.runOnNativeModulesQueueThread(setupReactContextRunnable); UiThreadUtil.runOnUiThread(maybeRecreateReactContextRunnable);} catch (Exception e) {this.mDevSupportManager.handleException(e);}}, "create_react_context");ReactMarker.logMarker(ReactMarkerConstants.REACT_CONTEXT_THREAD_START);this.mCreateReactContextThread.start();}

createReactContext方法就会创建CatalystInstanceImpl
wdf,这玩意挺复杂的,别着急慢慢来, CatalystInstanceImpl → JNI → Hermes/JSC ,hahaha

http://www.hskmm.com/?act=detail&tid=36131

相关文章:

  • 以TrustedInstaller/System用户运行软件
  • 10月21号
  • 机器学习基础 -- 线性回归模型
  • 泰勒展开
  • MySQL 创建和授权用户
  • 因果机器学习算法新进展解析
  • 软件工程作业三
  • CF2127 Atto Round 1 (Codeforces Round 1041, Div. 1 + Div. 2) 游记(VP)
  • 一键生成爆款文章,并自动发布!
  • 机器学习到深度学习发展历程
  • Java数据类型
  • [CF 516 E] Drazil and His Happy Friends
  • NVIDIA Triton服务器漏洞危机:攻击者可远程执行代码,AI模型最高权限告急
  • 2025-10-21
  • 个人骗分导论
  • Java三大特性
  • 高级程序设计第二次作业
  • 10月21日日记
  • home-assistant.-Adding integrations
  • Windows系统内存占用过高,且任务管理器找不到对应进程
  • NOIP 二十五
  • 理想婚姻
  • equal和hashcode
  • Ancestral Problem 题解
  • AWS IAM角色最佳实践:构建云安全的核心防线
  • 正睿 2025 NOIP 20连测 Day6
  • Hetao P5593 删 题解 [ 蓝 ] [ 线性 DP ] [ DFS 序 ] [ 虚树 ]
  • o(N^2)找出所有回文子串
  • 第二次高级程序作业
  • 大学生需要认真听课的肌肉记忆(注意力训练)