React Native 启动流程 (Android版)
React Native 启动流程 (Android版)
我们从骨架项目MainActivity说起.其继承实现了ReactActivity.
进入MainActivity,先反射MainActivity执行其父类ReactActivity和自己的构造方法。
/** Base Activity for React Native applications. */
public abstract class ReactActivity extends AppCompatActivity
implements DefaultHardwareBackBtnHandler, PermissionAwareActivity {
private final ReactActivityDelegate mDelegate;
protected ReactActivity() {
mDelegate = createReactActivityDelegate();
}
@Override
protected 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实际上是其父类ReactActivityDelegate的onCreate的方法。
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注册的名字,我这边叫HelloWorld
final 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 { // 2
mReactDelegate =
new ReactDelegate(
getPlainActivity(), // activity
getReactNativeHost(), // Application的reactNativeHost
mainComponentName, // HelloWorld
launchOptions,
isFabricEnabled()) { // fabricEnabled = true
@Override
protected 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 surface
if (ReactNativeFeatureFlags.enableBridgelessArchitecture()) {
if (mReactSurface == null) {
mReactSurface = mReactHost.createSurface(mActivity, appKey, mLaunchOptions);
}
mReactSurface.start();
} else { // 1
if (mReactRootView != null) {
throw new IllegalStateException("Cannot loadApp while app is already running.");
}
mReactRootView = createRootView();
mReactRootView.startReactApplication( // 2
getReactNativeHost().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 instance
Assertions.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 measure
if (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 = true
if (!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() {
@Override
public void onPackagerStatusFetched(final boolean packagerIsRunning) {
UiThreadUtil.runOnUiThread(
() -> {
// ReactInstanceManager is no longer valid, ignore callback
if (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); // 2
this.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();
}
/**
* @return instance of {@link ReactContext} configured a {@link CatalystInstance} set
*/
private ReactApplicationContext createReactContext(
JavaScriptExecutor jsExecutor, JSBundleLoader jsBundleLoader) {
FLog.d(ReactConstants.TAG, "ReactInstanceManager.createReactContext()");
ReactMarker.logMarker(CREATE_REACT_CONTEXT_START, jsExecutor.getName());
final BridgeReactContext reactContext = new BridgeReactContext(mApplicationContext);
JSExceptionHandler exceptionHandler =
mJSExceptionHandler != null ? mJSExceptionHandler : mDevSupportManager;
reactContext.setJSExceptionHandler(exceptionHandler);
NativeModuleRegistry nativeModuleRegistry = processPackages(reactContext, mPackages);
CatalystInstanceImpl.Builder catalystInstanceBuilder =
new CatalystInstanceImpl.Builder()
.setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
.setJSExecutor(jsExecutor)
.setRegistry(nativeModuleRegistry)
.setJSBundleLoader(jsBundleLoader)
.setJSExceptionHandler(exceptionHandler)
.setInspectorTarget(getOrCreateInspectorTarget());
ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_START);
// CREATE_CATALYST_INSTANCE_END is in JSCExecutor.cpp
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "createCatalystInstance");
final CatalystInstance catalystInstance;
try {
catalystInstance = catalystInstanceBuilder.build();
} finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_END);
}
reactContext.initializeWithInstance(catalystInstance);
// On Old Architecture, we need to initialize the Native Runtime Scheduler so that
// the `nativeRuntimeScheduler` object is registered on JS.
// On New Architecture, this is normally triggered by instantiate a TurboModuleManager.
// Here we invoke getRuntimeScheduler() to trigger the creation of it regardless of the
// architecture so it will always be there.
catalystInstance.getRuntimeScheduler();
if (ReactNativeFeatureFlags.useTurboModules() && mTMMDelegateBuilder != null) {
TurboModuleManagerDelegate tmmDelegate =
mTMMDelegateBuilder
.setPackages(mPackages)
.setReactApplicationContext(reactContext)
.build();
TurboModuleManager turboModuleManager =
new TurboModuleManager(
catalystInstance.getRuntimeExecutor(),
tmmDelegate,
catalystInstance.getJSCallInvokerHolder(),
catalystInstance.getNativeMethodCallInvokerHolder());
catalystInstance.setTurboModuleRegistry(turboModuleManager);
// Eagerly initialize TurboModules
for (String moduleName : turboModuleManager.getEagerInitModuleNames()) {
turboModuleManager.getModule(moduleName);
}
}
if (mUIManagerProvider != null) {
UIManager uiManager = mUIManagerProvider.createUIManager(reactContext);
if (uiManager != null) {
catalystInstance.setFabricUIManager(uiManager);
// Initialize the UIManager
uiManager.initialize();
catalystInstance.setFabricUIManager(uiManager);
}
}
if (mBridgeIdleDebugListener != null) {
catalystInstance.addBridgeIdleDebugListener(mBridgeIdleDebugListener);
}
if (BuildConfig.ENABLE_PERFETTO
|| Systrace.isTracing(TRACE_TAG_REACT_APPS | TRACE_TAG_REACT_JS_VM_CALLS)) {
catalystInstance.setGlobalVariable("__RCTProfileIsProfiling", "true");
}
ReactMarker.logMarker(ReactMarkerConstants.PRE_RUN_JS_BUNDLE_START);
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "runJSBundle");
catalystInstance.runJSBundle(); // 1
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
return reactContext;
}
ss
facebook/react-native/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.kt
private fun getDefaultJSExecutorFactory(
appName: String,
deviceName: String,
applicationContext: Context,
): JavaScriptExecutorFactory? {
ReactInstanceManager.initializeSoLoaderIfNecessary(applicationContext)
// Hermes has been enabled by default in OSS since React Native 0.70.
try {
HermesExecutor.loadLibrary()
return HermesExecutorFactory()
} catch (error: UnsatisfiedLinkError) {
FLog.e(
TAG,
"Unable to load Hermes. Your application is not built correctly and will fail to execute",
)
return null
}
}
facebook/react-native/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoader.kt
/** A class that stores JS bundle information and allows a [JSBundleLoaderDelegate]. */
public abstract class JSBundleLoader {
/** Loads the script, returning the URL of the source it loaded. */
public abstract fun loadScript(delegate: JSBundleLoaderDelegate): String
public companion object {
/**
* This loader is recommended one for release version of your app. In that case local JS
* executor should be used. JS bundle will be read from assets in native code to save on passing
* large strings from java to native memory.
*/
@JvmStatic
public fun createAssetLoader(
context: Context,
assetUrl: String,
loadSynchronously: Boolean,
): JSBundleLoader =
object : JSBundleLoader() {
override fun loadScript(delegate: JSBundleLoaderDelegate): String {
delegate.loadScriptFromAssets(context.assets, assetUrl, loadSynchronously) // 1
return assetUrl
}
}
delegate实际上就是CatalystInstanceImpl。
createReactContext方法就会创建CatalystInstanceImpl,然后加载jsBundle.
wdf,这玩意挺复杂的,别着急慢慢来, CatalystInstanceImpl → JNI → Hermes/JSC ,hahaha
CatalystInstanceImpl
@DoNotStrip
public class CatalystInstanceImpl implements CatalystInstance {
static {
ReactBridge.staticInit(); // 1
}
private CatalystInstanceImpl(
final ReactQueueConfigurationSpec reactQueueConfigurationSpec,
final JavaScriptExecutor jsExecutor,
final NativeModuleRegistry nativeModuleRegistry,
final JSBundleLoader jsBundleLoader,
JSExceptionHandler jSExceptionHandler,
@Nullable ReactInstanceManagerInspectorTarget inspectorTarget) {
FLog.d(ReactConstants.TAG, "Initializing React Xplat Bridge.");
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "createCatalystInstanceImpl");
mHybridData = initHybrid();
mReactQueueConfiguration =
ReactQueueConfigurationImpl.create(
reactQueueConfigurationSpec, new NativeExceptionHandler());
mBridgeIdleListeners = new CopyOnWriteArrayList<>();
mNativeModuleRegistry = nativeModuleRegistry;
mJSModuleRegistry = new JavaScriptModuleRegistry();
mJSBundleLoader = jsBundleLoader;
mJSExceptionHandler = jSExceptionHandler;
mNativeModulesQueueThread = mReactQueueConfiguration.getNativeModulesQueueThread();
mTraceListener = new JSProfilerTraceListener(this);
mInspectorTarget = inspectorTarget;
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
FLog.d(ReactConstants.TAG, "Initializing React Xplat Bridge before initializeBridge");
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "initializeCxxBridge");
initializeBridge(
new InstanceCallback(this),
jsExecutor,
mReactQueueConfiguration.getJSQueueThread(),
mNativeModulesQueueThread,
mNativeModuleRegistry.getJavaModules(this),
mNativeModuleRegistry.getCxxModules(),
mInspectorTarget);
FLog.d(ReactConstants.TAG, "Initializing React Xplat Bridge after initializeBridge");
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
mJavaScriptContextHolder = new JavaScriptContextHolder(getJavaScriptContext());
}
@Override
public void runJSBundle() {
FLog.d(ReactConstants.TAG, "CatalystInstanceImpl.runJSBundle()");
Assertions.assertCondition(!mJSBundleHasLoaded, "JS bundle was already loaded!");
// incrementPendingJSCalls();
mJSBundleLoader.loadScript(CatalystInstanceImpl.this);
synchronized (mJSCallsPendingInitLock) {
// Loading the bundle is queued on the JS thread, but may not have
// run yet. It's safe to set this here, though, since any work it
// gates will be queued on the JS thread behind the load.
mAcceptCalls = true;
for (PendingJSCall function : mJSCallsPendingInit) {
function.call(this);
}
mJSCallsPendingInit.clear();
mJSBundleHasLoaded = true;
}
// This is registered after JS starts since it makes a JS call
Systrace.registerListener(mTraceListener);
}
}
代码1处进行JNI函数注册.
packages/react-native/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp
extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
#ifdef WITH_XPLATINIT
return facebook::xplat::initialize(vm, [] {
#else
return jni::initialize(vm, [] {
#endif
#if WITH_GLOGINIT
gloginit::initialize();
FLAGS_minloglevel = 0;
#endif
ProxyJavaScriptExecutorHolder::registerNatives();
CatalystInstanceImpl::registerNatives();
CxxModuleWrapperBase::registerNatives();
JCxxCallbackImpl::registerNatives();
NativeArray::registerNatives();
ReadableNativeArray::registerNatives();
WritableNativeArray::registerNatives();
NativeMap::registerNatives();
ReadableNativeMap::registerNatives();
WritableNativeMap::registerNatives();
JDynamicNative::registerNatives();
JReactMarker::registerNatives();
JInspector::registerNatives();
ReactInstanceManagerInspectorTarget::registerNatives();
InspectorNetworkRequestListener::registerNatives();
});
}

React Native 启动流程 (Android版)
浙公网安备 33010602011771号