React Native 启动流程 (Android版)

news/2025/10/21 22:33:44/文章来源:https://www.cnblogs.com/zshsboke/p/19156585

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.mzph.cn/news/942735.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NOIP 二十六

区间DPA. 圆心处向周围连边就将整个圆分成了若干个不相关的部分。断环成链,记 \(f[l, r]\) 为 \([l, r]\) 内连通的最小代价,转移考虑是否选择 \((l, r)\) 这条边。 枚举分界点转移。 注意当目前区间大于半圆的时候不…

Say 题选记 (10.19 - 10.25)

P3702 [SDOI2017] 序列计数 首先至少 1 个质数可以容斥成随便选 - 只选合数。然后注意到第二维很小,直接矩阵快速幂即可。Code #include <bits/stdc++.h> using namespace std; const int M = 2e7 + 5, K = 1e2…

宝塔面板

为什么需要宝塔面板linux终端是一个全是命令行的东西,不便于管理因此安装宝塔面板,就是一个服务器的可视化桌面或者控制中心一键安装运行环境(最核心的便利) 你想在服务器上搭建一个网站,通常需要安装:Web服务器…

泰勒展开

我们不妨令 \(x\geq x_0\)。 \[f(x) = f(x_0) + \int^x_{x_0}f(t)\text{d}t \]然后我们换一下积分变量。 \[f(x) = f(x_0) + \int^x_{x_0}f(t)\text{d}(t - x) \]然后我们分部积分。 \[f(x) = f(x_0) + \int^x_{x_0}(t…

机器学习基础 -- 线性回归模型

线性回归模型在机器学习中,线性回归模型是一种基础的模型算法,其数学原理通过最小二乘法使欧式距离(均方误差)最小化来求出w和b。本篇文章将介绍一些数学原理,给定几个数据并通过scikit-learn库中集成的LinearReg…

因果机器学习算法新进展解析

某中心将新型因果机器学习算法开源至DoWhy库,这些算法基于图形因果模型,能执行根因分析、因果结构学习和分布变化归因等复杂因果查询,已在供应链和云服务等多个场景得到实际应用。开源因果机器学习算法 我们很高兴宣…

一键生成爆款文章,并自动发布!

最近在疯狂的玩 n8n,也越来越发现他的强大之处了。 同时也感叹目前的 AI 生态真的很完善,而且 AI 的成果也越来越好了,甚至可以超过很多普通人。 这不,今天刚搭建了一个:一键生成小红书爆款文章,并自动发布的工作…

软件工程作业三

计算机科学与技术 王阿丽亚阿不来海提 3223004639 计算机科学与技术 阿依古再丽艾力
3223004595这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience这个作业要求在哪里 https:…

1188. 设计有限阻塞队列

1188. 设计有限阻塞队列 题目描述实现一个拥有如下方法的线程安全有限阻塞队列:BoundedBlockingQueue(int capacity) 构造方法初始化队列,其中capacity代表队列长度上限。void enqueue(int element) 在队首增加一个e…

MySQL 创建和授权用户

查看所有用户 SELECT user, host FROM mysql.user;查看指定用户的权限 SELECT * FROM mysql.user WHERE user=root创建和授权用户创建一个用户CREATE USER readonly@% IDENTIFIED BY 123456;给用户赋予只读权限GRANT S…

MySQL分页解决方案

一、深分页问题背景 当分页偏移量(OFFSET)过大时(如LIMIT 100000, 20),MySQL需要扫描并丢弃前100,000条记录,导致:查询性能急剧下降 服务器资源浪费 响应时间变长二、解决方案详解 1. 游标查询(Cursor-based P…

二维坐标旋转公式推导

二维坐标旋转公式一、核心概念 在二维坐标系中,一个点围绕某个旋转中心旋转时,其坐标会发生变化。 旋转可分为两种情况:绕坐标原点 (0,0) 旋转 绕任意点 (cx, cy) 旋转推导基于三角函数与极坐标的关系。二、绕原点 …

Failed to resolve: org.webrtc:google-webrtc:1.0.32006

参考文章:https://blog.csdn.net/rosyrays1/article/details/148427678 这是一个在安卓端实现音视频功能时遇到的问题 解决方案2: gradle dependencies方式: 使用一些开源社区自制仓库的webrtc包名 比如这个(亲测可…

云计算简单算法练习题

云计算简单算法练习题 No1 LCR 128. 库存管理 I 仓库管理员以数组 stock 形式记录商品库存表。stock[i] 表示商品 id,可能存在重复。原库存表按商品 id 升序排列。现因突发情况需要进行商品紧急调拨,管理员将这批商品…

机器学习到深度学习发展历程

一、传统机器学习时代(2000-2012) 这一时期代表了深度学习革命前夕的机器学习黄金时代。支持向量机、决策树集成方法等技术在理论和实践上都达到了成熟,为后续深度学习的发展提供了重要的理论基础和实践经验。 支持…

Java三大特性

OOP 面向对象三大特性:封装、继承、多态、(抽象) 1.封装 只暴露对象的公开属性和方法,无法看到内部实现过程;对象功能内聚,模块之间的耦合降低,更有维护性。 设计模式七大原则之一的迪米特原则,是对封装的具体要…

日总结 15

C# 和 Java 作为两种主流的面向对象编程语言,虽语法相似(均源于 C 系),但在设计目标、生态、特性等方面差异显著,核心区别可总结如下:历史与定位 C#:微软 2000 年推出,早期绑定 Windows 的.NET Framework,后通…

[CF 516 E] Drazil and His Happy Friends

A 侧有 \(n\) 个点,B 侧有 \(m\) 个点,从 \(0\) 开始标号。已知初始有若干黑点,其它都是白点。第 \(i\)(\(i \ge 0\))时刻,若 A 的第 \(i \bmod n\) 个点和 B 的第 \(i \bmod m\) 个点中存在一个黑色的点,则两个…

NVIDIA Triton服务器漏洞危机:攻击者可远程执行代码,AI模型最高权限告急

NVIDIA Triton服务器漏洞危机:攻击者可远程执行代码,AI模型最高权限告急漏洞概述NVIDIA公司面向Windows和Linux系统的Triton Inference Server(一个用于大规模运行人工智能模型的开源平台)近日披露了一组安全漏洞,…

高级程序设计第二次作业

姓名:王志勇 学号:102500434 3.11编程题第一到第八题: 1. 2. 3. 4. 5. 6. 7. 8. 3.1-3.5,3.8-3.9的示例程序结果输出: 3.1 3.2 3.3 3.4 3.5 3.8 3.9