dwqs / dwqs/blog

从 Hello World 看 RN 的启动流程(二)

Open
#76 1 comment 2 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
3.8k
Forks
443
PR merge metrics
No merged PRs in 30d

Description

### CatalystInstanceImpl
[前文](https://github.com/dwqs/blog/issues/75)提到了 `CatalystInstance` 是一个接口类型,但其继承了 `JSBundleLoaderDelegate` 接口,后者定义了不同的 js bundle 加载方法声明:

```java
// reac-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoaderDelegate.java

// ...
public interface JSBundleLoaderDelegate {
// 从 Android assets 加载 bundle
void loadScriptFromAssets(AssetManager assetManager, String assetURL, boolean loadSynchronously);

// 从文件系统加载 bundle,用于自定义 bundle 加载路径
void loadScriptFromFile(String fileName, String sourceURL, boolean loadSynchronously);

// 从 Metro 中加载增量 bundle
void loadScriptFromDeltaBundle(
String sourceURL, NativeDeltaClient deltaClient, boolean loadSynchronously);

void setSourceURLs(String deviceURL, String remoteURL);
}

```

我们首先来看下类 `CatalystInstance` 的子类 `CatalystInstanceImpl` 的构造方法:

```java
// reac-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java

// ...
public class CatalystInstanceImpl implements CatalystInstance {

// ...

// C++ 层
private final HybridData mHybridData;
private static native HybridData initHybrid();
public native JSCallInvokerHolderImpl getJSCallInvokerHolder();

private CatalystInstanceImpl(
final ReactQueueConfigurationSpec reactQueueConfigurationSpec,
final JavaScriptExecutor jsExecutor,
final NativeModuleRegistry nativeModuleRegistry,
final JSBundleLoader jsBundleLoader,
NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler) {

// 略去日志输出代码

// C++ 方法,用来创建JNI(Java Native Interface)相关状态
mHybridData = initHybrid();

// 初始化线程配置(即上文提到的 Native Modules、js以及UI线程)
mReactQueueConfiguration =
ReactQueueConfigurationImpl.create(
reactQueueConfigurationSpec, new NativeExceptionHandler());
mBridgeIdleListeners = new CopyOnWriteArrayList<>();
mNativeModuleRegistry = nativeModuleRegistry;
mJSModuleRegistry = new JavaScriptModuleRegistry();
mJSBundleLoader = jsBundleLoader;
mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler;
mNativeModulesQueueThread = mReactQueueConfiguration.getNativeModulesQueueThread();
mTraceListener = new JSProfilerTraceListener(this);

// 略去日志输出代码

// C++方法,用来初始化Bridge,并创建BridgeCallback实例
initializeBridge(
new BridgeCallback(this),
jsExecutor,
mReactQueueConfiguration.getJSQueueThread(),
mNativeModulesQueueThread,
mNativeModuleRegistry.getJavaModules(this),
mNativeModuleRegistry.getCxxModules());

// ...
}

// ...

private native void initializeBridge(
ReactCallback callback,
JavaScriptExecutor jsExecutor,
MessageQueueThread jsQueue,
MessageQueueThread moduleQueue,
Collection javaModules,
Collection cxxModules);

// ...

public CatalystInstanceImpl build() {
return new CatalystInstanceImpl(
Assertions.assertNotNull(mReactQueueConfigurationSpec),
Assertions.assertNotNull(mJSExecutor),
Assertions.assertNotNull(mRegistry),
Assertions.assertNotNull(mJSBundleLoader),
Assertions.assertNotNull(mNativeModuleCallExceptionHandler));
}
}

// ...
```

`initializeBridge` 方法的参数说明如下:

* callback: CatalystInstanceImpl 的静态内部类 BridgeCallback 实例 ,负责接口回调
* jsExecutor: js 执行器实例,将 js 的调用传递给 C++ 层
* jsQueue:js 线程
* moduleQueue: Native Modules 线程
* javaModules: Java Modules
* cxxModules: C++ Modules

从这可以看出,js 和 Java 之间并不直接通信,而是以 C++ 作为中间层。

除了 `initializeBridge` 方法,方法 `initHybrid` 和 `getJSCallInvokerHolder` 都是 Native C++ 方法,我们先看下 `CatalystInstanceImpl.cpp` 注册的方法:

```cpp
// react-native/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp

// ...
void CatalystInstanceImpl::registerNatives() {
registerHybrid({
makeNativeMethod("initHybrid", CatalystInstanceImpl::initHybrid),
makeNativeMethod("initializeBridge", CatalystInstanceImpl::initializeBridge),
// ...
// 后文会提到 jniLoadScriptFromAssets 方法
makeNativeMethod("jniLoadScriptFromAssets", CatalystInstanceImpl::jniLoadScriptFromAssets),
// ...
makeNativeMethod("jniExtendNativeModules", CatalystInstanceImpl::getJSCallInvokerHolder),
// ...
});

JNativeRunnable::registerNatives();
}
// ...
```

然后简单看下方法 `initializeBridge` 的 C++ 实现:

```cpp
// react-native/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp

void CatalystInstanceImpl::initializeBridge(
jni::alias_ref callback,
// This executor is actually a factory holder.
JavaScriptExecutorHolder* jseh,
jni::alias_ref jsQueue,
jni::alias_ref nativeModulesQueue,
jni::alias_ref::javaobject> javaModules,
jni::alias_ref::javaobject> cxxModules) {
// TODO mhorowitz: how to assert here?
// Assertions.assertCondition(mBridge == null, "initializeBridge should be called once");
moduleMessageQueue_ = std::make_shared(nativeModulesQueue);

moduleRegistry_ = std::make_shared(
buildNativeModuleList(
std::weak_ptr(instance_),
javaModules,
cxxModules,
moduleMessageQueue_));

/**
* instance_ 是类 Instance 的实例
* Instance.cpp 位于 react-native/ReactCommon/cxxreact 目录
* 后文还会提到这个
*/
instance_->initializeBridge(
std::make_unique(
callback,
moduleMessageQueue_),
jseh->getExecutorFactory(),
folly::make_unique(jsQueue),
moduleRegistry_);
}
```

到此,类 `CatalystInstanceImpl` 的实例初始化就完成了,同时通过 `initializeBridge` 方法建立了 Bridge 连接(Java <--> C++ <--> JS )。在实例初始化后,就调用了实例的 `runJSBundle` 方法开始加载 js bundle:

```java
// reac-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java

// ...

public void runJSBundle() {
// ...

mJSBundleLoader.loadScript(CatalystInstanceImpl.this);

// ...
}

// ...
```

### JSBundleLoader
在 `runJSBundle` 方法中,实际上会去调用 `JSBundleLoader` 实例的 `loadScript` 方法。

在[前文](https://github.com/dwqs/blog/issues/75)初始化 `ReactInstanceManager` 实例时,提到了 `JSBundleLoader` 实例化。对于不同的场景,会有不同的 `JSBundleLoader` 实例化方式,而在创建 `ReactInstanceManager` 实例时,默认的实现是 `JSBundleLoader#createAssetLoader`:

```java
// react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java

// ...
return new ReactInstanceManager(
mApplication,
mCurrentActivity,
mDefaultHardwareBackBtnHandler,
mJavaScriptExecutorFactory == null
? getDefaultJSExecutorFactory(appName, deviceName)
: mJavaScriptExecutorFactory,
(mJSBundleLoader == null && mJSBundleAssetUrl != null)
? JSBundleLoader.createAssetLoader(
mApplication, mJSBundleAssetUrl, false /*Asynchronous*/)
: mJSBundleLoader,
// ...
);

// ...

// react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoader.java
// ...
public abstract class JSBundleLoader {
// ...
public static JSBundleLoader createAssetLoader(
final Context context, final String assetUrl, final boolean loadSynchronously) {
return new JSBundleLoader() {
@Override
public String loadScript(JSBundleLoaderDelegate delegate) {
delegate.loadScriptFromAssets(context.getAssets(), assetUrl, loadSynchronously);
return assetUrl;
}
};
}

// ...
}
// ...
```

可以看到它会继续调用 `CatalystInstanceImpl` 实例中的 `loadScriptFromAssets` 方法:

```java
//...

public void loadScriptFromAssets(
AssetManager assetManager, String assetURL, boolean loadSynchronously) {
mSourceURL = assetURL;
jniLoadScriptFromAssets(assetManager, assetURL, loadSynchronously);
}

// ...

// C++ 方法
private native void jniLoadScriptFromAssets(
AssetManager assetManager, String assetURL, boolean loadSynchronously);

// ...
```

上文已经提到了 `jniLoadScriptFromAssets` 方法的注册是在 `CatalystInstanceImpl.cpp` 中,具体看其实现:

```cpp
void CatalystInstanceImpl::jniLoadScriptFromAssets(
jni::alias_ref assetManager,
const std::string& assetURL,
bool loadSynchronously) {
const int kAssetsLength = 9; // strlen("assets://");
// 获取 js Bundle 的路径名,一般默认值是 index.android.bundle
auto sourceURL = assetURL.substr(kAssetsLength);

/**
* 调用 JSLoader.cpp 中的 extractAssetManager 方法提取 AssetManager
* 返回值来自于系统动态链接库 android/asset_manager_jni.h的AAssetManager_fromJava方法
*/
auto manager = extractAssetManager(assetManager);

// 调用JSLoader.cpp的loadScriptFromAssets()方法读取JS Bundle里的内容
auto script = loadScriptFromAssets(manager, sourceURL);

/**
* 是否是unbundle命令打包
* RN Android 打包用了 react.gradle 的默认bundle,没用unbundle命令
*/
if (JniJSModulesUnbundle::isUnbundle(manager, sourceURL)) {
auto bundle = JniJSModulesUnbundle::fromEntryFile(manager, sourceURL);
auto registry = RAMBundleRegistry::singleBundleRegistry(std::move(bundle));
instance_->loadRAMBundle(
std::move(registry),
std::move(script),
sourceURL,
loadSynchronously);
return;
} else if (Instance::isIndexedRAMBundle(&script)) {
// 是否是 RAMBundle ???
instance_->loadRAMBundleFromString(std::move(script), sourceURL);
} else {
// 调用类 Instance 实例的 loadScriptFromString 方法
instance_->loadScriptFromString(std::move(script), sourceURL, loadSynchronously);
}
}
```

继续看 `Instance.cpp` 中 `loadScriptFromString` 方法的实现:

```cpp
// react-native/ReactCommon/cxxreact/Instance.cpp

/**
* string为index.android.bundle内容
* sourceURL 默认是 index.android.bundle
*/
void Instance::loadScriptFromString(std::unique_ptr string,
std::string sourceURL,
bool loadSynchronously) {
SystraceSection s("Instance::loadScriptFromString", "sourceURL",
sourceURL);
if (loadSynchronously) {
loadApplicationSync(nullptr, std::move(string), std::move(sourceURL));
} else {
loadApplication(nullptr, std::move(string), std::move(sourceURL));
}
}
```

在 `loadScriptFromString` 方法中,根据是否异步调用不同的方法。根据上文分析,`loadSynchronously` 的值是 `false`,所以会继续调用 `loadApplication` 方法:

```cpp
// react-native/ReactCommon/cxxreact/Instance.cpp

void Instance::loadApplication(std::unique_ptr bundleRegistry,
std::unique_ptr string,
std::string sourceURL) {

/**
* callback_ 是在 Java 中调用 initializeBridge 传进来的,其实现是
CatalystInstanceImpl的BridgeCallback
* 这里调用回调应该是告诉 Java 端要加载 bundle 了
*/
callback_->incrementPendingJSCalls();
SystraceSection s("Instance::loadApplication", "sourceURL",
sourceURL);

/**
* nativeToJsBridge_ 是类 NativeToJsBridge.cpp 的实例
* 是在 Instance::initializeBridge方法里初始化的
*/
nativeToJsBridge_->loadApplication(std::move(bundleRegistry), std::move(string),
std::move(sourceURL));
}
```

继续看 `NativeToJsBridge::loadApplication` 的实现:

```cpp
// react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp

void NativeToJsBridge::loadApplication(
std::unique_ptr bundleRegistry,
std::unique_ptr startupScript,
std::string startupScriptSourceURL) {

// 获取一个 MessageQueueThread,然后在其线程中执行一个task
runOnExecutorQueue(
[this,
bundleRegistryWrap=folly::makeMoveWrapper(std::move(bundleRegistry)),
startupScript=folly::makeMoveWrapper(std::move(startupScript)),
startupScriptSourceURL=std::move(startupScriptSourceURL)]
(JSExecutor* executor) mutable {
auto bundleRegistry = bundleRegistryWrap.move();
if (bundleRegistry) {
executor->setBundleRegistry(std::move(bundleRegistry));
}
try {
/**
* 进一步调用 JSExecutor::loadApplicationScript 方法,
* 调用到这里时,才真正去加载 js bundle,并解析 js
* startupScript 是 bundle 字符串
* startupScriptSourceURL 是 bundle url
*/
executor->loadApplicationScript(std::move(*startupScript),
std::move(startupScriptSourceURL));
} catch (...) {
m_applicationScriptHasFailure = true;
throw;
}
});
}

//
```

到这里,离终点就差一步了。这差的一步就是 `JSExecutor` 类并没有实现 `loadApplicationScript` 方法:

```cpp
// react-native/ReactCommon/cxxreact/JSExecutor.cpp

#include "JSExecutor.h"
#include "RAMBundleRegistry.h"
#include

namespace facebook {
namespace react {

std::string JSExecutor::getSyntheticBundlePath(
uint32_t bundleId,
const std::string& bundlePath) {
if (bundleId == RAMBundleRegistry::MAIN_BUNDLE_ID) {
return bundlePath;
}
return folly::to("seg-", bundleId, ".js");
}

}
}
```

但头文件 `JSExecutor.h` 中却包含了 `loadApplicationScript` 的声明,这说明是由类 `JSExecutor` 的子类实现了 `loadApplicationScript` 方法。

但它的子类是谁呢?

### 寻找 JSExecutor 的子类

回到 Java 中最初创建 js 执行器工厂实例的地方:

```java
// react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java

// ...
return new ReactInstanceManager(
mApplication,
mCurrentActivity,
mDefaultHardwareBackBtnHandler,
mJavaScriptExecutorFactory == null
? getDefaultJSExecutorFactory(appName, deviceName)
: mJavaScriptExecutorFactory,
(mJSBundleLoader == null && mJSBundleAssetUrl != null)
? JSBundleLoader.createAssetLoader(
mApplication, mJSBundleAssetUrl, false /*Asynchronous*/)
: mJSBundleLoader,
// ...
);

private JavaScriptExecutorFactory getDefaultJSExecutorFactory(String appName, String deviceName) {
try {
// 加载 C++ 层的 jscexecutor,优先考虑使用 JSC 引擎
SoLoader.loadLibrary("jscexecutor");
return new JSCExecutorFactory(appName, deviceName);
} catch (UnsatisfiedLinkError jscE) {
// JSC 加载失败,就使用 Hermes 引擎
return new HermesExecutorFactory();
}
}
```

`getDefaultJSExecutorFactory` 方法会先去加载 `jscexecutor` 库,然后返回一个 `JSCExecutorFactory` 实例:

```java
// react-native/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutorFactory.java

// 实现接口 JavaScriptExecutorFactory
public class JSCExecutorFactory implements JavaScriptExecutorFactory {
private final String mAppName;
private final String mDeviceName;

public JSCExecutorFactory(String appName, String deviceName) {
this.mAppName = appName;
this.mDeviceName = deviceName;
}

@Override
public JavaScriptExecutor create() throws Exception {
WritableNativeMap jscConfig = new WritableNativeMap();
jscConfig.putString("OwnerIdentity", "ReactNative");
jscConfig.putString("AppIdentity", mAppName);
jscConfig.putString("DeviceIdentity", mDeviceName);
return new JSCExecutor(jscConfig);
}

// ...
}
```

`jscexecutor` 库加载完成之后,会去注册 C++ 方法 `initHybrid`:

```cpp
// react-native/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/OnLoad.cpp

// ...

class JSCExecutorHolder
: public jni::HybridClass {
public:
static constexpr auto kJavaDescriptor =
"Lcom/facebook/react/jscexecutor/JSCExecutor;";

static jni::local_ref initHybrid(
jni::alias_ref,
ReadableNativeMap *) {
// ...

// TODO mhorowitz T28461666 fill in some missing nice to have glue
return makeCxxInstance(folly::make_unique());
}

// 注册 initHybrid 方法供 Java 端调用
static void registerNatives() {
registerHybrid({
makeNativeMethod("initHybrid", JSCExecutorHolder::initHybrid),
});
}
// ...
};

// ...

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
return facebook::jni::initialize(
vm, [] { facebook::react::JSCExecutorHolder::registerNatives(); });
}
```

顺着 Java 的调用链继续往下走,来到[前文](https://github.com/dwqs/blog/issues/75)提到的创建 ReactContext 的地方:

```java
// reac-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java

// ...

private class ReactContextInitParams {
private final JavaScriptExecutorFactory mJsExecutorFactory;
private final JSBundleLoader mJsBundleLoader;

public ReactContextInitParams(
JavaScriptExecutorFactory jsExecutorFactory, JSBundleLoader jsBundleLoader) {
mJsExecutorFactory = Assertions.assertNotNull(jsExecutorFactory);
mJsBundleLoader = Assertions.assertNotNull(jsBundleLoader);
}

public JavaScriptExecutorFactory getJsExecutorFactory() {
return mJsExecutorFactory;
}

public JSBundleLoader getJsBundleLoader() {
return mJsBundleLoader;
}
}

// ...

private void recreateReactContextInBackground(
JavaScriptExecutorFactory jsExecutorFactory, JSBundleLoader jsBundleLoader) {

// ...

final ReactContextInitParams initParams =
new ReactContextInitParams(jsExecutorFactory, jsBundleLoader);

// ...

runCreateReactContextOnNewThread(initParams);

// ...
}

// ...

private void runCreateReactContextOnNewThread(final ReactContextInitParams initParams) {
// ...
// 创建 ReactContext
final ReactApplicationContext reactApplicationContext =
createReactContext(
// 返回 JavaScriptExecutorFactory 实例并且调用 create 方法
initParams.getJsExecutorFactory().create(),
initParams.getJsBundleLoader());

mCreateReactContextThread = null;
// ...
}
// ...
```

上文提到了 `JSCExecutorFactory` 类实现了接口 `JavaScriptExecutorFactory`,同时从上文可以看到 `create` 方法返回的是 `JSCExecutor` 实例:

```java
// react-native/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutor.java

// ...
// 实现抽象类 JavaScriptExecutor
@DoNotStrip
class JSCExecutor extends JavaScriptExecutor {
// ...

JSCExecutor(ReadableNativeMap jscConfig) {
/**
* 调用父类的构造函数,参数是 C++ 方法 initHybrid 的返回值
* 上文已经说过,jscexecutor 库加载完成之后,就会注册 initHybrid 方法供 Java 端调用
* JavaScriptExecutor 类的构造函数中仅仅是保存该返回值
*/
super(initHybrid(jscConfig));
}

@Override
public String getName() {
return "JSCExecutor";
}

private static native HybridData initHybrid(ReadableNativeMap jscConfig);
}

```

继续回到上文的 `OnLoad.cpp` 中查看调用链:

```cpp
// react-native/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/OnLoad.cpp

// ...

#include

// ...

// 继承 JSExecutorFactory 类
class JSCExecutorFactory : public JSExecutorFactory {
public:
std::unique_ptr createJSExecutor(
std::shared_ptr delegate,
std::shared_ptr jsQueue) override {
auto installBindings = [](jsi::Runtime &runtime) {
react::Logger androidLogger =
static_cast(
&reactAndroidLoggingHook);
react::bindNativeLogger(runtime, androidLogger);
};
return folly::make_unique(
jsc::makeJSCRuntime(),
delegate,
JSIExecutor::defaultTimeoutInvoker,
installBindings);
}
};

// ...

class JSCExecutorHolder
// ...

static jni::local_ref initHybrid(
jni::alias_ref,
ReadableNativeMap *) {
// ...

return makeCxxInstance(folly::make_unique());
}

// ...
```

从上述代码可以看到,`initHybrid` 方法最终返回了 `JSIExecutor` 实例。继续往下看头文件 `JSIExecutor.h` 的声明:

```cpp
// react-native/ReactCommon/jsiexecutor/jsireact/JSIExecutor.h

// ...

class JSIExecutor : public JSExecutor {
public:
using RuntimeInstaller = std::function;
// 构造函数声明
JSIExecutor(
std::shared_ptr runtime,
std::shared_ptr delegate,
const JSIScopedTimeoutInvoker &timeoutInvoker,
RuntimeInstaller runtimeInstaller);
void loadApplicationScript(
std::unique_ptr script,
std::string sourceURL) override;

// ...
}

// ...
```

至此,我们找到了类 `JSExecutor` 的子类 `JSIExecutor`,并看到其头文件中对 `loadApplicationScript` 方法的声明。

### JSIExecutor.cpp
找到了 `loadApplicationScript` 方法的声明,那就可以看其具体的实现了:

```cpp
// react-native/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp

// ...
/**
* script: bundle 内容(字符串)
* sourceURL: bundle 地址
*/
void JSIExecutor::loadApplicationScript(
std::unique_ptr script,
std::string sourceURL) {

// 略去一些全局设置和 debug 下的代码

if (runtimeInstaller_) {
runtimeInstaller_(*runtime_);
}

// 略去日志输出代码

// 关键代码:使用 webkit JSC 去真正解释执行Javascript了
runtime_->evaluateJavaScript(
std::make_unique(std::move(script)), sourceURL);
flush();

// 略去日志输出代码
}

// ...

void JSIExecutor::flush() {
SystraceSection s("JSIExecutor::flush");
// flushedQueue_ 还没被赋值,继续往下走
if (flushedQueue_) {
callNativeModules(flushedQueue_->call(*runtime_), true);
return;
}

/**
* BatchedBridge.enqueueNativeCall 方法是否被调用过(如果 js 调用过 Java 模块,该方法也会被调用),如果被调用过,
* 会在 global 对象上定义一个 __fbBatchedBridge 属性,其值是 BatchedBridge
* BatchedBridge 是 MessageQueue 的一个实例,
* 具体见:react-native/Libraries/BatchedBridge/BatchedBridge.js
*/
Value batchedBridge =
runtime_->global().getProperty(*runtime_, "__fbBatchedBridge");
if (!batchedBridge.isUndefined()) {
// 还没被调用过

// 调用 bindBridge 方法绑定 js bridge,见下文
bindBridge();
callNativeModules(flushedQueue_->call(*runtime_), true);
} else if (delegate_) {
callNativeModules(nullptr, true);
}
}

// ...

void JSIExecutor::bindBridge() {
std::call_once(bindFlag_, [this] {
SystraceSection s("JSIExecutor::bindBridge (once)");
Value batchedBridgeValue =
runtime_->global().getProperty(*runtime_, "__fbBatchedBridge");
if (batchedBridgeValue.isUndefined()) {
throw JSINativeException(
"Could not get BatchedBridge, make sure your bundle is packaged correctly");
}

Object batchedBridge = batchedBridgeValue.asObject(*runtime_);
callFunctionReturnFlushedQueue_ = batchedBridge.getPropertyAsFunction(
*runtime_, "callFunctionReturnFlushedQueue");
invokeCallbackAndReturnFlushedQueue_ = batchedBridge.getPropertyAsFunction(
*runtime_, "invokeCallbackAndReturnFlushedQueue");
/**
* 对 flushedQueue_ 进行赋值
* 通过webkit JSC 获取 MessageQueue.js 的 flushedQueue 属性值(函数)
*/
flushedQueue_ =
batchedBridge.getPropertyAsFunction(*runtime_, "flushedQueue");
callFunctionReturnResultAndFlushedQueue_ =
batchedBridge.getPropertyAsFunction(
*runtime_, "callFunctionReturnResultAndFlushedQueue");
});
}

void JSIExecutor::callNativeModules(const Value &queue, bool isEndOfBatch) {
SystraceSection s("JSIExecutor::callNativeModules");
// If this fails, you need to pass a fully functional delegate with a
// module registry to the factory/ctor.
CHECK(delegate_) << "Attempting to use native modules without a delegate";
#if 0
// 将函数 flushedQueue_ 的返回值 json 化
std::string json = runtime_->global().getPropertyAsObject(*runtime_, "JSON")
.getPropertyAsFunction(*runtime_, "stringify").call(*runtime_, queue)
.getString(*runtime_).utf8(*runtime_);
#endif
// 调用 delegate_ 的 callNativeModules 方法
delegate_->callNativeModules(
*this, dynamicFromValue(*runtime_, queue), isEndOfBatch);
}

// ...
```

在 `JSIExecutor` 的构造函数声明中可以看到,`delegate_` 是类 `ExecutorDelegate` 的实例,其声明是在头文件 `JSExecutor.h` 中。

但类 `ExecutorDelegate` 是一个虚拟类,方法 `callNativeModules` 是一个虚拟方法(可类比 Java 中的抽象类和抽象方法来理解),因而这里实际调用的是其子类的对应方法:

```cpp
// react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp

// ...
class JsToNativeBridge : public react::ExecutorDelegate {
public:
// 构造函数
JsToNativeBridge(std::shared_ptr registry,
std::shared_ptr callback)
: m_registry(registry)
, m_callback(callback) {}


// 重写父类的 callNativeModules
void callNativeModules(
__unused JSExecutor& executor, folly::dynamic&& calls, bool isEndOfBatch) override {

CHECK(m_registry || calls.empty()) <<
"native module calls cannot be completed with no native modules";
m_batchHadNativeModuleCalls = m_batchHadNativeModuleCalls || !calls.empty();

for (auto& call : parseMethodCalls(std::move(calls))) {
// 调用 Native Registry 表中的java NativeMethod方法。
m_registry->callNativeMethod(call.moduleId, call.methodId, std::move(call.arguments), call.callId);
}
// isEndOfBatch 的值是 true
if (isEndOfBatch) {

// onBatchComplete will be called on the native (module) queue, but
// decrementPendingJSCalls will be called sync. Be aware that the bridge may still
// be processing native calls when the bridge idle signaler fires.
if (m_batchHadNativeModuleCalls) {
/**
* 回调 Java 端,通知 Java 端 js bundle 已经加载完成
* m_callback 是 Java 类 BridgeCallback 的实例
*/
m_callback->onBatchComplete();
m_batchHadNativeModuleCalls = false;
}
m_callback->decrementPendingJSCalls();
}
}
// ...
```

看到这里,你可能想知道 `m_callback` 是哪来的?

我们回想一下调用链路,在创建 `CatalystInstance` 实例的时候,同时会调用 C++ 层的 `CatalystInstanceImpl::initializeBridge` 方法,传入的第一个实数就是 `BridgeCallback` 实例,对应 C++ 层方法中第一个形参 `callback`。而在 `CatalystInstanceImpl::initializeBridge` 方法中又会调用 `Instance::initializeBridge` 方法,同时将 `callback` 作为一个参数透传,在 `Instance::initializeBridge` 方法中又会初始化 `NativeToJsBridge` 实例,同时将包装后的 `callback` 作为最后一个参数透传,在类 `NativeToJsBridge` 的构造函数中会初始化 `JsToNativeBridge`,将 `callback` 透传。

至此,js bundle 加载和解析流程完成了,我们回到Java代码中看看后续的流程。

### 回到 ReactInstanceManager

`createReactContext` 方法返回之后,继续往后执行:

```java
// reac-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java

// ...

private void runCreateReactContextOnNewThread(final ReactContextInitParams initParams) {
// ...
final ReactApplicationContext reactApplicationContext =
createReactContext(
initParams.getJsExecutorFactory().create(),
initParams.getJsBundleLoader());

mCreateReactContextThread = null;
// ...

Runnable setupReactContextRunnable =
new Runnable() {
@Override
public void run() {
try {
setupReactContext(reactApplicationContext);
} catch (Exception e) {
mDevSupportManager.handleException(e);
}
}
};

reactApplicationContext.runOnNativeModulesQueueThread(setupReactContextRunnable);
// ...
}
```

当线程任务 `setupReactContextRunnable` 启动之后,会去调用 `setupReactContext` 方法:

```java
// reac-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java

// ...
private void setupReactContext(final ReactApplicationContext reactContext) {
// ...

synchronized (mAttachedReactRoots) {
synchronized (mReactContextLock) {
mCurrentReactContext = Assertions.assertNotNull(reactContext);
}

CatalystInstance catalystInstance =
Assertions.assertNotNull(reactContext.getCatalystInstance());

// 初始化 Native Modules
catalystInstance.initialize();

// ...

// 遍历 mAttachedReactRoots
for (ReactRoot reactRoot : mAttachedReactRoots) {
attachRootViewToInstance(reactRoot);
}
ReactMarker.logMarker(ATTACH_MEASURED_ROOT_VIEWS_END);
}

// ...
}
// ...
```

先简单追溯一下 `mAttachedReactRoots` 被赋值的链路:`mAttachedReactRoots` 是在 `ReactInstanceManager#attachRootView` 方法中被赋值,`attachRootView` 方法是在 `ReactRootView#attachToReactInstanceManager` 方法中被调用,参数是 `ReactRootView` 实例,所以 `mAttachedReactRoots` 中保存的都是 `ReactRootView` 实例。

继续看 `attachRootViewToInstance` 方法的实现:

```java
// reac-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java

// ...
private void attachRootViewToInstance(final ReactRoot reactRoot) {
// ...

// 将ReactRootView作为根布局
UIManager uiManager =
UIManagerHelper.getUIManager(mCurrentReactContext, reactRoot.getUIManagerType());

// 获取初始化参数
@Nullable Bundle initialProperties = reactRoot.getAppProperties();

// 获取 rootTag
final int rootTag =
uiManager.addRootView(
reactRoot.getRootViewGroup(),
initialProperties == null
? new WritableNativeMap()
: Arguments.fromBundle(initialProperties),
reactRoot.getInitialUITemplate());

// 设置 RootView 的 rootTag
reactRoot.setRootViewTag(rootTag);

// RootView 的类型判断,默认类型是 DEFAULT
if (reactRoot.getUIManagerType() == FABRIC) {
// Fabric requires to call updateRootLayoutSpecs before starting JS Application,
// this ensures the root will hace the correct pointScaleFactor.
uiManager.updateRootLayoutSpecs(
rootTag, reactRoot.getWidthMeasureSpec(), reactRoot.getHeightMeasureSpec());
reactRoot.setShouldLogContentAppeared(true);
} else {
// 调用 runApplication 方法
reactRoot.runApplication();
}

// ...
}
// ...
```

### 回到 ReactRootView
继续看 `runApplication` 方法的实现:

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

// ...

import com.facebook.react.modules.appregistry.AppRegistry;

// ...
public void runApplication() {

// ...

ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
if (reactContext == null) {
return;
}

CatalystInstance catalystInstance = reactContext.getCatalystInstance();

/**
* 获取 module name
* 这个 module name 就是在 js 端调用 registerComponent 的第一个参数
*/
String jsAppModuleName = getJSModuleName();

if (mUseSurface) {
// TODO call surface's runApplication
} else {
if (mWasMeasured) {
updateRootLayoutSpecs(mWidthMeasureSpec, mHeightMeasureSpec);
}

// 包装 RN 应用启动时的初始化参数
WritableNativeMap appParams = new WritableNativeMap();
appParams.putDouble("rootTag", getRootViewTag());
@Nullable Bundle appProperties = getAppProperties();
if (appProperties != null) {
appParams.putMap("initialProps", Arguments.fromBundle(appProperties));
}

mShouldLogContentAppeared = true;

// 启动 RN 应用的入口
catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams);
}
} finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
}
}
// ...
```

`AppRegistry` 类是 js 层暴露给 Java 层 JS module,所有的 JS module 都是接口,不能直接调用。但通过**代理对象**(`AppRegistry.class`),Java 对 JS 的调用就会有一个统一的入口:

```java
// reac-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaScriptModuleRegistry.java

// ...
@Override
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
NativeArray jsArgs = args != null ? Arguments.fromJavaArgs(args) : new WritableNativeArray();
mCatalystInstance.callFunction(getJSModuleName(), method.getName(), jsArgs);
return null;
}
// ...
```

从上述代码可知,所有 Java 对 JS 的调用都是通过 `CatalystInstance#callFunction` 方法实现,但最终都是通过 C++ 中的 `CatalystInstanceImpl::jniCallJSFunction` 方法实现的。

`AppRegistry` 类的具体实现在 `AppRegistry.js` 中:

```js

// ...

registerComponent(
appKey: string,
componentProvider: ComponentProvider,
section?: boolean,
): string {

runnables[appKey] = {
componentProvider,
/**
* appParameters 是原生端初始化 RN 应用时透传的参数
* 属性主要包含用于初始化的 initialProps,rootTag,fabric等
*/
run: appParameters => {
renderApplication(
// ...
)
},
};

// ...
return appKey;
},

// ...
runApplication(appKey: string, appParameters: any): void {
// ...
runnables[appKey].run(appParameters);
},
// ...
```

`run` 方法会去调用 `renderApplication` 方法去渲染 JS 组件,那 js 组件怎么和 Native 组件对应呢?

上文说到了,js bundle 执行之后会回调 Java:

```cpp
// ...
/**
* 回调 Java 端,通知 Java 端 js bundle 已经加载完成
* m_callback 是 Java 类 BridgeCallback 的实例
*/
m_callback->onBatchComplete();
m_batchHadNativeModuleCalls = false;
// ...
```

类 `BridgeCallback` 是 `CatalystInstanceImpl` 类的一个私有类,继续顺着调用链往下走:

```
BridgeCallback#onBatchComplete --> NativeModuleRegistry#onBatchComplete 找到 UIManager 接口模块
--> UIManagerModule#onBatchComplete --> UIImplementation#dispatchViewUpdates
```

`UIManagerModule` 类是 `UIManager` 接口的实现,其主要作用是桥接 JS 层去创建和更新 Native views,而 `UIImplementation` 类的主要作用将 JS 层的 React node 转为 Shadow node,便于后续和 Native views 作映射。从而,现有架构下的渲染原理如下图所示:

![image](https://user-images.githubusercontent.com/7871813/62845064-19aa1900-bcf8-11e9-92df-3523146b4c10.png)

而 Fabric 架构出来之后,就没有 `UIManager` 模块了,取而代之的是 `FabricUIManager`,并将 Shadow 层从 Java 层移到了 C++ 层,这也是 Fabric 能提升 RN 性能的一个原因所在。

<本文完>

## 参考
* [React Native Android 源码框架浅析](https://blog.csdn.net/yanbober/article/details/53157456)
* [庖丁解牛!深入剖析 React Native 下一代架构重构](https://www.infoq.cn/article/EJYNuQ2s1XZ88lLa*2XT)

Contributor guide

No contributing guide indexed for this repository

Research direction

This is a long Chinese walkthrough rather than a concrete change request. Start with the named ReactAndroid files CatalystInstanceImpl.java, JSBundleLoader.java, and CatalystInstanceImpl.cpp, then follow the references to ReactCommon/cxxreact/Instance.cpp and NativeToJsBridge.cpp. No acceptance criteria or definition of done is stated, so confirm the intended documentation update before proceeding.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, java, javascript
Domain
documentation
Issue type
Documentation
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.