Android-ReactNative通信流程

ReactAndroid

ReactActivity

一个ReactActivity对应着一个RN组件(通过AppRegistry.registerComponent注册),而ReactActivity的功能都包装在ReactActivityDelegate中。

ReactActivity实际上类似于一个浏览器窗口,在一个窗口内对一个网页访问,并进行页面的跳转和回退。

ReactRootView

ReactRootView是ReactNative组件的根布局,是一个ViewGroup(继承自FrameLayout),所有的RN视图都会被添加到该布局下,然后该布局会被添加到Activity上,因此每个ReactActivity都有着一个ReactRootView。RN组件内的页面跳转实际上就是在该ReactRootView上重绘。

ReactNativeHost

每个RN组件的配置,设置jsbundle文件的文件名和js模块名称以及开发模式等。

  • getJSMainModuleName : 远程服务获取bundle时,获取的模块名称
  • getBundleAssetName : 本地加载bundle时,获取asset文件的文件名
  • getUseDeveloperSupport : 是否开启debug模式
  • getPackages : 配置js和native通信module,必须包含MainReactPackage
  • ReactInstanceManager : 与js通信的管理类,CatalystInstance是一个异步JSC桥梁,提供了调用js方法的JavaAPI

每个ReactActivity都需要一个Host配置,对应不同的jsbundle配置。在ReactActivity中默认会去获取Application中的ReactNativeHost,默认Application需要继承ReactApplication接口,并实现其getReactNativeHost方法。如果我们不想在Application中实现该接口(必须我们有多个RN组件需要多个ReactNativeHost对象),就必须重写ReactActivity中getReactNativeHost方法。

1
2
3
protected ReactNativeHost getReactNativeHost() {
return ((ReactApplication) getPlainActivity().getApplication()).getReactNativeHost();
}

加载RN组件

启动ReactActivity

首先启动ReactActivity,创建ReactActivity时会同时创建ReactActivityDelegate,ReactActivity的getMainComponentName方法对应的是js组件的注册名称(js中AppRegistry.registerComponent注册时的appKey),在ReactActivity的onCreate回调中,开始加载该js组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
protected void onCreate(Bundle savedInstanceState) {
if (mMainComponentName != null) {
loadApp(mMainComponentName);
}
}

protected void loadApp(String appKey) {
if (mReactRootView != null) {
throw new IllegalStateException("Cannot loadApp while app is already running.");
}
// 创建根布局
mReactRootView = createRootView();
// 启动该js组件,加载jsbundle文件,并通过jsc来构建virtualDom来解析js组件
// 将js控件解析成对应的View,并添加到根布局上,组成视图树。
mReactRootView.startReactApplication(
// 创建js通信管理器
getReactNativeHost().getReactInstanceManager(),
appKey,
getLaunchOptions());
// 将解析完成的布局放到Activity中渲染
getPlainActivity().setContentView(mReactRootView);
}
创建ReactRootView

ReactRootView继承FrameLayout,是整个RN组件的根布局,解析出来的View都会添加到该布局上。该View主要处理了测量和事件的分发拦截,包括触摸、手势、焦点等。还设置了OnGlobalLayout监听,该方法会在布局重新layout或者系统UI发生改变时触发(具体在ViewRootImpl.performTraversals中),在该监听中将发生的改变通知给js模块。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public void onGlobalLayout() {
if (mReactInstanceManager == null || !mIsAttachedToInstance ||
mReactInstanceManager.getCurrentReactContext() == null) {
return;
}
// 键盘状态改变
checkForKeyboardEvents();
// 屏幕方向改变
checkForDeviceOrientationChanges();
// 屏幕分辨率改变
checkForDeviceDimensionsChanges();
}
创建ReactInstanceManager

ReactInstanceManager是一个CatalystInstance实例的管理者,而CatalysInstance是一个异步的JSC桥梁,负责与js进行通信,调用js方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
protected ReactInstanceManager createReactInstanceManager() {
// 获取ReactNativeHost中的配置来创建
ReactInstanceManagerBuilder builder = ReactInstanceManager.builder()
.setApplication(mApplication)
.setJSMainModulePath(getJSMainModuleName())
.setUseDeveloperSupport(getUseDeveloperSupport())
.setRedBoxHandler(getRedBoxHandler())
.setJavaScriptExecutorFactory(getJavaScriptExecutorFactory())
.setUIImplementationProvider(getUIImplementationProvider())
.setJSIModulesPackage(getJSIModulePackage())
.setInitialLifecycleState(LifecycleState.BEFORE_CREATE);
for (ReactPackage reactPackage : getPackages()) {
builder.addPackage(reactPackage);
}
String jsBundleFile = getJSBundleFile();
if (jsBundleFile != null) {
builder.setJSBundleFile(jsBundleFile);
} else {
builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName()));
}
ReactInstanceManager reactInstanceManager = builder.build();
return reactInstanceManager;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public ReactInstanceManager build() {
// 创建ReactInstanceManager
return new ReactInstanceManager(
mApplication, // 应用Application
mCurrentActivity, // 当前ReactActivity
mDefaultHardwareBackBtnHandler, // 处理js不处理的硬件回退事件
mJavaScriptExecutorFactory == null // JSC执行器
// 用来创建JSC执行器的工厂
? new JSCJavaScriptExecutorFactory(appName, deviceName)
: mJavaScriptExecutorFactory,
(mJSBundleLoader == null && mJSBundleAssetUrl != null) // JSBundle加载器
? JSBundleLoader.createAssetLoader(
// 创建一个匿名实例,从Assets中加载jsbundle
mApplication, mJSBundleAssetUrl, false /*Asynchronous*/)
: mJSBundleLoader,
mJSMainModulePath, // Host中配置的js模块名称
mPackages, // Host中配置的通信module
mUseDeveloperSupport, // Host中配置的debug
mBridgeIdleDebugListener, // Bridge空闲状态监听
Assertions.assertNotNull(mInitialLifecycleState, "Initial lifecycle state was not set"),
mUIImplementationProvider, // 用来在UIManagerModule中创建UIImplementation
mNativeModuleCallExceptionHandler, // JS调用native出异常的处理类
mRedBoxHandler, // RedBox就是JS错误的红色页面,该接口可以拦截和处理其页面上的错误信息。
mLazyNativeModulesEnabled,
mLazyViewManagersEnabled,
mDevBundleDownloadListener,
mMinNumShakes,
mMinTimeLeftInFrameForNonBatchedOperationMs,
mJSIModulesPackage);
}

当使用JSBundleLoader去加载jsbundle文件时,就会调用该匿名实例的loadScript方法从assets中加载。

1
2
3
4
5
6
7
8
9
10
11
12
public static JSBundleLoader createAssetLoader(
final Context context,
final String assetUrl,
final boolean loadSynchronously) {
return new JSBundleLoader() {
@Override
public String loadScript(CatalystInstanceImpl instance) {
instance.loadScriptFromAssets(context.getAssets(), assetUrl, loadSynchronously);
return assetUrl;
}
};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
ReactInstanceManager(...) {
// 构造函数
...
synchronized (mPackages) {
PrinterHolder.getPrinter()
.logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: Use Split Packages");
mPackages.add(
// 添加CoreModulePackage通信模块
new CoreModulesPackage(
this,
new DefaultHardwareBackBtnHandler() {
@Override
public void invokeDefaultOnBackPressed() {
ReactInstanceManager.this.invokeDefaultOnBackPressed();
}
},
uiImplementationProvider,
lazyViewManagersEnabled,
minTimeLeftInFrameForNonBatchedOperationMs));
if (mUseDeveloperSupport) {
mPackages.add(new DebugCorePackage());
}
mPackages.addAll(packages);
}
mJSIModulePackage = jsiModulePackage;

// ReactChoreographer是对Choreographer的包装,用来在绘制一帧的时候执行一些自定义的回调
ReactChoreographer.initialize();
if (mUseDeveloperSupport) {
mDevSupportManager.startInspector();
}
}
启动jsbundle组件

在创建完ReactInstanceManager后,会通过它在后台异步创建ReactContext,最终逻辑在ReactInstanceManager.runCreateReactContextOnNewThread中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@ThreadConfined(UI)
private void recreateReactContextInBackground(
JavaScriptExecutorFactory jsExecutorFactory,
JSBundleLoader jsBundleLoader) {

final ReactContextInitParams initParams = new ReactContextInitParams(
jsExecutorFactory,
jsBundleLoader);
if (mCreateReactContextThread == null) {
// 此时代表ReactContext已经创建过程已经结束或未开始,可以直接重新创建
runCreateReactContextOnNewThread(initParams);
} else {
// 此时代表正在创建ReactContext,需要等待
mPendingReactContextInitParams = initParams;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  @ThreadConfined(UI)
private void runCreateReactContextOnNewThread(final ReactContextInitParams initParams) {
UiThreadUtil.assertOnUiThread();
mCreateReactContextThread =
new Thread(
new Runnable() {
@Override
public void run() {
...
mHasStartedCreatingInitialContext = true;
try {
// 提高线程的优先级,避免被UI线程中途抢占
Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
// 创建ReactApplicationContext
final ReactApplicationContext reactApplicationContext =
createReactContext(
// 通过工厂创建JSCScriptExecutor
initParams.getJsExecutorFactory().create(),
// 此处的Loader就是上面的匿名Loader
initParams.getJsBundleLoader());
// 在此之前如果其他地方需要重新创建Context,那么会先将参数放入mPendingReactContextInitParams中,再讲其放到主线程消息队列中稍后再次执行该方法。
// 在此之后如果需要重建,则重新创建一个线程启动就行
mCreateReactContextThread = null;
final Runnable maybeRecreateReactContextRunnable =
new Runnable() {
@Override
public void run() {
if (mPendingReactContextInitParams != null) {
//看见标记还在,重新创建ReactContext
runCreateReactContextOnNewThread(mPendingReactContextInitParams);
mPendingReactContextInitParams = null;
}
}
};
Runnable setupReactContextRunnable =
new Runnable() {
@Override
public void run() {
try {
// 启动ReactContext
setupReactContext(reactApplicationContext);
} catch (Exception e) {
mDevSupportManager.handleException(e);
}
}
};

// 在native线程中执行启动ReactContext任务
reactApplicationContext.runOnNativeModulesQueueThread(setupReactContextRunnable);
// 在主线程中启动重新创建任务
UiThreadUtil.runOnUiThread(maybeRecreateReactContextRunnable);
} catch (Exception e) {
mDevSupportManager.handleException(e);
}
}
});
mCreateReactContextThread.start();
}
创建ReactContext

ReactContext是对ContextWrapper的再次包装,实际上就是一个上下文,而ReactApplicationContext实际上就是ApplicationContext。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 private ReactApplicationContext createReactContext(
JavaScriptExecutor jsExecutor,
JSBundleLoader jsBundleLoader) {
final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);

NativeModuleCallExceptionHandler exceptionHandler = mNativeModuleCallExceptionHandler != null
? mNativeModuleCallExceptionHandler
: mDevSupportManager;
reactContext.setNativeModuleCallExceptionHandler(exceptionHandler);
// 解析mPackages中包含的module
NativeModuleRegistry nativeModuleRegistry = processPackages(reactContext, mPackages, false);
// 创建CatalysInstance的实现类实例
CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder()
// 创建js和native消息执行的线程命名配置
.setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
.setJSExecutor(jsExecutor)
.setRegistry(nativeModuleRegistry) // 解析mPackages后得到的已注册的module集合
.setJSBundleLoader(jsBundleLoader)
.setNativeModuleCallExceptionHandler(exceptionHandler);

final CatalystInstance catalystInstance;
try {
catalystInstance = catalystInstanceBuilder.build();
} finally {
}
if (mJSIModulePackage != null) {
catalystInstance.addJSIModules(mJSIModulePackage
.getJSIModules(reactContext, catalystInstance.getJavaScriptContextHolder()));
}

if (mBridgeIdleDebugListener != null) {
catalystInstance.addBridgeIdleDebugListener(mBridgeIdleDebugListener);
}
if (Systrace.isTracing(TRACE_TAG_REACT_APPS | TRACE_TAG_REACT_JS_VM_CALLS)) {
catalystInstance.setGlobalVariable("__RCTProfileIsProfiling", "true");
}
// 加载jsbundle
catalystInstance.runJSBundle();
// 将CatalystInstance实例和ReactContext关联
reactContext.initializeWithInstance(catalystInstance);

return reactContext;
}
创建CatalysInstanceImpl

CatalysInstanceImpl是与js通信的bridge的真正实现。ReactQueueConfigurationImpl中保存了三个线程,分别是UI线程,native执行的线程,js执行的线程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 private CatalystInstanceImpl(
final ReactQueueConfigurationSpec reactQueueConfigurationSpec,
final JavaScriptExecutor jsExecutor,
final NativeModuleRegistry nativeModuleRegistry,
final JSBundleLoader jsBundleLoader,
NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler) {
mHybridData = initHybrid(); // 调用jni方法创建HybridData对象
// 根据上面的js和native消息执行的线程命名配置,创建真正的线程实现MessageQueueThreadImpl,并启动这些线程,每个线程中都有一个looper在轮训消息。在MessageQueueThreadImpl中有一个mHandler,负责向这些线程的looper发送消息。
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);
// 调用jni方法
initializeBridge(
new BridgeCallback(this),
jsExecutor,
mReactQueueConfiguration.getJSQueueThread(),
mNativeModulesQueueThread,
mNativeModuleRegistry.getJavaModules(this),
mNativeModuleRegistry.getCxxModules());

mJavaScriptContextHolder = new JavaScriptContextHolder(getJavaScriptContext());
}

在加载CatalystInstanceImpl类时,加载了HybridData类,就会加载libfb.so,然后会执行上面说的动态注册jni方法。

1
2
3
4
5
public class HybridData {
static {
SoLoader.loadLibrary("fb");
}
}

initHybrid (C++层)

根据注册信息,我们知道会执行CatalysInstanceImpl.cpp中的initHybrid函数。该函数会在c++层创建一个com/facebook/jni/HybridData.java对象,然后将其返回保存在java层的CatalysInstanceImpl对象中。然后还会创建一个Hybrid.h/BaseHybridClass对象,然后将其对象指针设置给刚刚创建的HybridData对象(HybridData.mDestructor.mNativePointer)。

mNativePointer变量只是用来维护当前HybridData实例是否可用的标记(通过HybridData.isValid方法),当退出等操作时,会执行HybridData.resetNative来清空释放标记。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 # src/main/jni/react/jni/CatalysInstanceImpl.cpp 
jni::local_ref<CatalystInstanceImpl::jhybriddata> CatalystInstanceImpl::initHybrid(
jni::alias_ref<jclass>) {
return makeCxxInstance();
}

# src/main/jni/first-party/fb/include/fb/fbjni/Hybrid.h
static local_ref<detail::HybridData> makeHybridData(std::unique_ptr<T> cxxPart) {
// 创建一个com/facebook/jni/HybridData.java对象
auto hybridData = detail::HybridData::create();
setNativePointer(hybridData, std::move(cxxPart));
return hybridData;
}

# src/main/jni/first-party/fb/include/fb/fbjni/CoreClasses-inl.h
static local_ref<JC> newInstance(Args... args) {
// 获取com/facebook/jni/HybridData的class引用
static auto cls = JC::javaClassStatic();
static auto constructor = cls->template getConstructor<typename JC::javaobject(Args...)>();
// 创建该class实例
return cls->newObject(constructor, args...);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# src/main/jni/first-party/fb/include/fb/fbjni/Hybrid.h 
template<typename T>
void setNativePointer(T t, std::unique_ptr<detail::BaseHybridClass> new_value) {
getHolder(t)->setNativePointer(std::move(new_value));
}

template<typename T>
local_ref<HybridDestructor> getHolder(T t) {
// 获取com/facebook/jni/HybridData.java类中的mDestructor字段的值
static auto holderField = t->getClass()->template getField<HybridDestructor::javaobject>("mDestructor");
// 返回的是转换后的HybridDestructor对象
return t->getFieldValue(holderField);
}

template <typename T=detail::BaseHybridClass>
void setNativePointer(std::unique_ptr<T> new_value) {
// 获取com/facebook/jni/HybridData$Destructor类中的mNativePointer字段引用
static auto pointerField = javaClassStatic()->getField<jlong>("mNativePointer");
// 获取当前对象中该字段的值
auto old_value = std::unique_ptr<T>(reinterpret_cast<T*>(getFieldValue(pointerField)));
if (new_value && old_value) {
FBCRASH("Attempt to set C++ native pointer twice");
}
// new_value是BaseHybridClass对象实例的指针,将该指针设置到mNativePointer字段中
// 也就是设置到com/facebook/jni/HybridData$Destructor.mNativePointer中
setFieldValue(pointerField, reinterpret_cast<jlong>(new_value.release()));
}
initializeBridge (C++层)

在initializeBridge方法中,主要是创建了NativeToJsBridge对象,并将其实例保存在CatalystInstanceImpl.instance.nativeToJsBridge_中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# src/main/jni/react/jni/CatalysInstanceImpl.cpp
void CatalystInstanceImpl::initializeBridge(
jni::alias_ref<ReactCallback::javaobject> callback,
// This executor is actually a factory holder.
JavaScriptExecutorHolder* jseh,
jni::alias_ref<JavaMessageQueueThread::javaobject> jsQueue,
jni::alias_ref<JavaMessageQueueThread::javaobject> nativeModulesQueue,
jni::alias_ref<jni::JCollection<JavaModuleWrapper::javaobject>::javaobject> javaModules,
jni::alias_ref<jni::JCollection<ModuleHolder::javaobject>::javaobject> cxxModules) {
// 创建c++层的native消息线程
moduleMessageQueue_ = std::make_shared<JMessageQueueThread>(nativeModulesQueue);
// 将modules中的module转换成NativeModule对象,并绑定了module执行的线程也就是上面的native消息线程
// 创建ModuleRegistry对象,内部维护modules列表
moduleRegistry_ = std::make_shared<ModuleRegistry>(
buildNativeModuleList(
std::weak_ptr<Instance>(instance_),
javaModules,
cxxModules,
moduleMessageQueue_));
// instance 是cxxreact/Instance.h中定义的,在CatalystInstanceImpl创建时创建该对象并赋值给instance。
instance_->initializeBridge
// 创建JInstanceCallback对象,绑定传进来的callback和所执行的线程(native消息线程)
folly::make_unique<JInstanceCallback>(
callback,
moduleMessageQueue_),
jseh->getExecutorFactory(), // 得到JSCExecutorFactory
folly::make_unique<JMessageQueueThread>(jsQueue),//创建c++层的js消息线程
moduleRegistry_);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# cxxreact/Instance.cpp
void Instance::initializeBridge(
std::unique_ptr<InstanceCallback> callback,
std::shared_ptr<JSExecutorFactory> jsef,
std::shared_ptr<MessageQueueThread> jsQueue,
std::shared_ptr<ModuleRegistry> moduleRegistry) {
callback_ = std::move(callback);
moduleRegistry_ = std::move(moduleRegistry);
// 在js消息线程中创建NativeToJsBridge对象
jsQueue->runOnQueueSync([this, &jsef, jsQueue]() mutable {
// 在js消息线程中执行下列代码
// 创建NativeToJsBridge对象
nativeToJsBridge_ = folly::make_unique<NativeToJsBridge>(
jsef.get(), moduleRegistry_, jsQueue, callback_);

std::lock_guard<std::mutex> lock(m_syncMutex);
m_syncReady = true;
m_syncCV.notify_all();
});

CHECK(nativeToJsBridge_);
}

# src/main/jni/react/jni/JMessageQueueThread.cpp
void JMessageQueueThread::runOnQueueSync(std::function<void()>&& runnable) {
// 获取com/facebook/react/bridge/queue/MessageQueueThread.java对象的class引用,然后拿到其isOnThread方法引用
static auto jIsOnThread = JavaMessageQueueThread::javaClassStatic()->
getMethod<jboolean()>("isOnThread");

if (jIsOnThread(m_jobj)) {
wrapRunnable(std::move(runnable))();
} else {
std::mutex signalMutex;
std::condition_variable signalCv;
bool runnableComplete = false;
// 如果当前不是在主线程,通过获取方法引用来调用
// com/facebook/react/bridge/queue/MessageQueueThread.java对象的runOnQueue方法
// 该方法会将runnable通过Handler发送到js消息线程的消息队列中
runOnQueue([&] () mutable {
std::lock_guard<std::mutex> lock(signalMutex);

runnable();
runnableComplete = true;

signalCv.notify_one();
});

std::unique_lock<std::mutex> lock(signalMutex);
// 当前线程等待js线程执行完该runnable
signalCv.wait(lock, [&runnableComplete] { return runnableComplete; });
}
}
加载并运行jsbundle

通过JSBundleLoader去加载jsbundle.js文件,默认是从assets中加载,可以通过在ReactInstanceManagerBuilder中提前设置自己的JSBundleLoader,实现自己的加载逻辑。

1
2
3
4
5
@Override
public void runJSBundle() {
// 此处的Loader是上面的匿名Loader
mJSBundleLoader.loadScript(CatalystInstanceImpl.this);
}

所以执行的是instance.loadScriptFromAssets(context.getAssets(), assetUrl, loadSynchronously);最终调用的是jni方法jniLoadScriptFromAssets去加载。

jniLoadScriptFromAssets (C++层)

所谓unbundle,是是对bundle的优化,当一个bundle非常大时,如果一次性全部加载整个可能非常慢,也占内存,可以通过编译时开启unbundle特性来解决,将bundle分割成多个文件,使用时加载需要的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# src/main/jni/react/jni/CatalysInstanceImpl.cpp
void CatalystInstanceImpl::jniLoadScriptFromAssets(
// AssetManager引用
jni::alias_ref<JAssetManager::javaobject> assetManager,
// 文件名称
const std::string& assetURL,
// 是否同步加载,默认不同步加载
bool loadSynchronously) {
const int kAssetsLength = 9; // strlen("assets://");
auto sourceURL = assetURL.substr(kAssetsLength);
// 通过AssetManager.open加载文件流
auto manager = extractAssetManager(assetManager);
auto script = loadScriptFromAssets(manager, sourceURL);
if (JniJSModulesUnbundle::isUnbundle(manager, sourceURL)) {
// 加载的是unbundle
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 {
instance_->loadScriptFromString(std::move(script), sourceURL, loadSynchronously);
}
}

# cxxreact/NativeToJsBridge.cpp
void NativeToJsBridge::loadApplication(
std::unique_ptr<RAMBundleRegistry> bundleRegistry,
std::unique_ptr<const JSBigString> startupScript,
std::string startupScriptSourceURL) {
// 将消息发送到js消息线程中处理
runOnExecutorQueue(
[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));
}
// 在js消息线程中去解析js文件流
executor->loadApplicationScript(std::move(*startupScript),
std::move(startupScriptSourceURL));
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# cxxreact/JSCExecutor.cpp
void JSCExecutor::loadApplicationScript(
std::unique_ptr<const JSBigString> script,
std::string sourceURL) {
SystraceSection s(
"JSCExecutor::loadApplicationScript", "sourceURL", sourceURL);

std::string scriptName = simpleBasename(sourceURL);
ReactMarker::logTaggedMarker(
ReactMarker::RUN_JS_BUNDLE_START, scriptName.c_str());
String jsSourceURL(m_context, sourceURL.c_str());

// TODO t15069155: reduce the number of overrides here
#ifdef WITH_FBJSCEXTENSIONS
// WITH_FBJSCEXTENSIONS宏是否被定义,rn的jsc走这
if (auto fileStr = dynamic_cast<const JSBigFileString*>(script.get())) {
JSContextLock lock(m_context);
JSLoadSourceStatus jsStatus;

auto bcSourceCode = JSCreateSourceCodeFromFile(
fileStr->fd(), jsSourceURL, nullptr, &jsStatus);

switch (jsStatus) {
case JSLoadSourceIsCompiled:
// 如果js代码已经编译过
if (!bcSourceCode) {
throw std::runtime_error("Unexpected error opening compiled bundle");
}
// 运行js代码
evaluateSourceCode(m_context, bcSourceCode, jsSourceURL);
// js调用native请求处理
flush();

ReactMarker::logMarker(ReactMarker::CREATE_REACT_CONTEXT_STOP);
ReactMarker::logTaggedMarker(
ReactMarker::RUN_JS_BUNDLE_STOP, scriptName.c_str());
return;

case JSLoadSourceErrorVersionMismatch:
throw RecoverableError(explainLoadSourceStatus(jsStatus));

case JSLoadSourceErrorOnRead:
case JSLoadSourceIsNotCompiled:
// Not bytecode, fall through.
break;
}
}
#elif defined(__APPLE__)
// IOS使用系统的JSC
...
#endif
{
...
}
flush (C++层)

flush方法用于处理js中对native模块调用请求,m_flushedQueueJS执行的是MessageQueue.js中的flushedQueue方法,获取_queue数组,该数组中保存了js中对native模块的调用请求。在callNativeModules中会对请求列表一一处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# cxxreact/JSCExecutor.cpp
void JSCExecutor::flush() {
SystraceSection s("JSCExecutor::flush");

if (m_flushedQueueJS) {
callNativeModules(m_flushedQueueJS->callAsFunction({}));
return;
}
auto global = Object::getGlobalObject(m_context);
auto batchedBridgeValue = global.getProperty("__fbBatchedBridge");
if (!batchedBridgeValue.isUndefined()) {
bindBridge();
// 从js的调用队列中获取调用请求,然后依次调用指定module的方法
callNativeModules(m_flushedQueueJS->callAsFunction({}));
} else if (m_delegate) {
callNativeModules(Value::makeNull(m_context));
}
}
启动ReactContext

在native消息线程中执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
 private void setupReactContext(final ReactApplicationContext reactContext) {

CatalystInstance catalystInstance =
Assertions.assertNotNull(reactContext.getCatalystInstance());
// 安装所有的NativeModule,调用NativeModule.initialize
catalystInstance.initialize();
mDevSupportManager.onNewReactContextCreated(reactContext);
mMemoryPressureRouter.addMemoryPressureListener(catalystInstance);
moveReactContextToCurrentLifecycleState();

synchronized (mAttachedRootViews) {
for (ReactRootView rootView : mAttachedRootViews) {
// 将ReactRootView添加到UIManager中作为RootView,并启动js组件
attachRootViewToInstance(rootView, catalystInstance);
}
}

ReactInstanceEventListener[] listeners =
new ReactInstanceEventListener[mReactInstanceEventListeners.size()];
final ReactInstanceEventListener[] finalListeners =
mReactInstanceEventListeners.toArray(listeners);

UiThreadUtil.runOnUiThread(
new Runnable() {
@Override
public void run() {
for (ReactInstanceEventListener listener : finalListeners) {
listener.onReactContextInitialized(reactContext);
}
}
});
// 将js线程和native线程的优先级恢复默认
reactContext.runOnJSQueueThread(
new Runnable() {
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
}
});
reactContext.runOnNativeModulesQueueThread(
new Runnable() {
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
}
});
}
启动js组件

将RootView添加到UIManager中后,就调用js组件的进入点,启动js组件。具体调用原理可以看上一篇的Android-ReactNative通信流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
private void defaultJSEntryPoint() {
try {
if (mReactInstanceManager == null || !mIsAttachedToInstance) {
return;
}

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

CatalystInstance catalystInstance = reactContext.getCatalystInstance();

WritableNativeMap appParams = new WritableNativeMap();
appParams.putDouble("rootTag", getRootViewTag());
@Nullable Bundle appProperties = getAppProperties();
if (appProperties != null) {
appParams.putMap("initialProps", Arguments.fromBundle(appProperties));
}
if (getUIManagerType() == FABRIC) {
appParams.putBoolean("fabric", true);
}

mShouldLogContentAppeared = true;

String jsAppModuleName = getJSModuleName();
// 获取AppRegistry这个js模块,运行期runApplication方法,实际上运行的是AppRegistry.js的runApplication函数
catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams);
} finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
}
}
js组件运行 (JS层)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
runApplication(appKey: string, appParameters: any): void {
const msg =
'Running application "' +
appKey +
'" with appParams: ' +
JSON.stringify(appParameters) +
'. ' +
'__DEV__ === ' +
String(__DEV__) +
', development-level warning are ' +
(__DEV__ ? 'ON' : 'OFF') +
', performance optimizations are ' +
(__DEV__ ? 'OFF' : 'ON');
infoLog(msg);
BugReporting.addSource(
'AppRegistry.runApplication' + runCount++,
() => msg,
);
...
// 运行
runnables[appKey].run(appParameters);
},
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×