一、整体部分
整体看,分为三个部分
- Java层,即Android层,提供了Android的渲染工具及其他工具。
- C++层,完成Java层与JS层的通信,与JS代码运行层。
- JS层,即JavaScript层,提供给JS层的开发人员提供环境。
重要角色:
- ReactActivityDelegate: 是ReactActivity界面类的生命周期管理类。
- ReactInstanceManager: 是RN应用的管理总类,创建了
ReactContext
、CatalystInstance
等类,解析ReactPackage
生成映射表,配合ReactRootView
管理控件等功能。 - ReactContext: 继承与
ContextWrapper
,是RN应用中使用的上下文,可以使用getContext()
获取,来访问RN核心类。 - CatalystInstance: 是RN应用Java层、C++层、JS层的通信总管理类,管理Java层与JS层核心Module映射表与回调。
ReactRootView: 启动入口类,负责监听及分发事件、渲染元素。
JavaScriptModule: JsModule,负责JS到Java的映射调用格式声明,由CatalystInstance管理。
NativeModule: JavaModule,负责Java到JS的映射调用格式声明,也由CatalystInstance管理。
JavascriptModuleRegistry: JsModule映射表,负责将javaModule注册到CatalystInstance,通过Java动态代理调用JS。
- NativeModuleRegistry: JavaModule映射表,相反,暴露Java接口给JS。
以上为框架中重要的角色,当真正渲染UI时,使用的时Native代码层,RN的作用就是吧JS代码映射成Native代码来实现两端通信。
一、ReactActivity
对于Android开发者,程序入口为Activity的继承类。
- ReactRootView:RN入口,也是界面对象。
- ReactActivityDelegate:ReactActivity的生命周期及其他类的管理类。
- ReactInstanceManager:构建React环境,发送事件到JS层。
- ReactPackage:配置App需要加载的模块,添加的包会在
Application
文件中配置。
onCreate
ReactActivityDelegate
中会在ReactActivity
调用onCreate()
的生命周期中调用loadApp()
函数。protected void loadApp(String appKey) {
mReactDelegate.loadApp(appKey);
getPlainActivity().setContentView(mReactDelegate.getReactRootView());
}
...
public void loadApp(String appKey) {
if (mReactRootView != null) {
throw new IllegalStateException("Cannot loadApp while app is already running.");
}
mReactRootView = createRootView();
mReactRootView.startReactApplication(getReactNativeHost().getReactInstanceManager(), appKey, mLaunchOptions);
}
getReactInstanceManager()
ReactinstanceManager
对象也是在ReactActivityDelegate
中创建。public ReactInstanceManager getReactInstanceManager() {
return mReactDelegate.getReactInstanceManager();
}ReactinstanceManager
调用createReactContext()
创建了CatalystInstance
。加载指定JS文件后,就会启动App,后面会加以描述。
注意这里的getReactInstanceManager()
创建的ReactInstanceManager
对象。因为里面会有许多重要工作。protected ReactInstanceManager createReactInstanceManager() {
ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_START);
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();
ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_END);
return reactInstanceManager;
}
1.处理Modules Package
2.创建CatalystInstance需要的builder
3.获取JS Bundle文件加载路径
对于RN,所有的Native组件与JS组件都需要分别继承NativeModule
和JavaScriptModule
类,并且都需要在CatalystInstance
中注册。Native组件与JS组件都被封装进相应的ReactPackage
中。
NativeModule:负责向JS端提供可用的接口,这些接口由Native端实现。内部的
createNativeModules()
与createViewManagers()
负责完成对组件的接口与UI的创建工具。
JavaScriptModule:负责向Native端提供可用的接口,这些接口由JS端实现。内部的createJSModules()
来返回内部包含的内容。注意该接口已于0.47版本删除
在创建ReactInstanceManager
时会创建CoreModulesPackage
对象。
CoreModulesPackage
CoreModulesPackage:定义并组装了核心框架模块(如UIManager),通常用于需要与其他模块集成的模块。
这里则分别定义了核心框架和自定义框架:...
synchronized (mPackages) {
PrinterHolder.getPrinter()
.logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: Use Split Packages");
mPackages.add(
new CoreModulesPackage(
this,
new DefaultHardwareBackBtnHandler() {
@Override
public void invokeDefaultOnBackPressed() {
ReactInstanceManager.this.invokeDefaultOnBackPressed();
}
},
mUIImplementationProvider,
lazyViewManagersEnabled,
minTimeLeftInFrameForNonBatchedOperationMs));
if (mUseDeveloperSupport) {
mPackages.add(new DebugCorePackage());
}
mPackages.addAll(packages);
}
...
上述代码中,会分别添加核心库CoreModulesPackage
和自定义库packages
,并且根据需要添加DebugCore
库。
然后会在createReactContext()
函数中对这些库进行注册。
createReactContext()
这里开始就会开启React的Application,进入到mCreateReactContextThread
线程中的createReactContext()
函数。
首先会将上述的核心库CroeModulesPackage
与自定义库packages
合并的mPackages
通过processPackages()
函数进行注册。保存在NativeModuleRegistryBuilder
类中的Map集合中。
同时会创建ReactApplicationContext
,其内部会封装Application Context
、CatalystInstance
对象和RN框架的三大线程。
其中在createReactContext()
函数中调用了runJSBundle()
来加载JS层代码。该代码就在CatalysInstance
类中。
而后的setupReactContext()
函数则会在js层代码准备完毕后,完成Native页面渲染,调用attachRootViewToInstance()
函数来完成。...
mCreateReactContextThread = new Thread(null, new Runnable() {
@Override
public void run() {
final ReactApplicationContext reactApplicationContext =
createReactContext(
initParams.getJsExecutorFactory().create(),
initParams.getJsBundleLoader());
...
Runnable setupReactContextRunnable = new Runnable() {
@Override
public void run() {
try {
setupReactContext(reactApplicationContext);
} catch (Exception e) {
mDevSupportManager.handleException(e);
}
}
};
}
}, "create_react_context");
ReactMarker.logMarker(REACT_CONTEXT_THREAD_START);
mCreateReactContextThread.start();
以下为createReactContext
函数内容:private ReactApplicationContext createReactContext(
JavaScriptExecutor jsExecutor, JSBundleLoader jsBundleLoader) {
ReactMarker.logMarker(CREATE_REACT_CONTEXT_START, jsExecutor.getName());
// 创建ReactApplicationContext
final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);
// 开启debug模式里异常处理器
NativeModuleCallExceptionHandler exceptionHandler =
mNativeModuleCallExceptionHandler != null
? mNativeModuleCallExceptionHandler
: mDevSupportManager;
reactContext.setNativeModuleCallExceptionHandler(exceptionHandler);
// 创建JavaModule注册表
NativeModuleRegistry nativeModuleRegistry = processPackages(reactContext, mPackages, false);
// 创建CatalystInstanceImpl中的builder
CatalystInstanceImpl.Builder catalystInstanceBuilder =
new CatalystInstanceImpl.Builder()
// 包含了创建的消息队列和配置信息
.setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
// JS执行器
.setJSExecutor(jsExecutor)
// java module注册表
.setRegistry(nativeModuleRegistry)
// JSBundle加载器
.setJSBundleLoader(jsBundleLoader)
// JavaException 处理器
.setNativeModuleCallExceptionHandler(exceptionHandler);
// 构建对象
try {
catalystInstance = catalystInstanceBuilder.build();
} finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_END);
}
// 关联ReactApplicationContext
reactContext.initializeWithInstance(catalystInstance);
// 开启加载执行JS Bundle
catalystInstance.runJSBundle();
return reactContext;
}
其中两个重要参数:JavaScriptExecutor
、JSBundleLoader
。
- JavaScriptExecutor:该类加载时,会自动加载
reactnativejnifb.so
库,并且会调用Native层的initHybrid()
函数,用来初始化C++层RN与JSC通信的框架。 - JSBundleLoader:缓存了
JSBundle
对象,不同的场景会创建不同的Loader
。封装了加载JSBundle
的相关接口loadScript()
。
总结
1.Activity开启时调用
onCreate()
生命周期函数。
2.调用ReactActivityDelegate
的onCreate()
函数,并调用内部的loadApp()
函数,并在内部调用startReactApplication()
函数。
3.这个过程首先会通过getReactInstanceManager()
函数创建我们需要的核心框架CoreModulesPackage
以及自定义部分框架,并准备CatalystInstance
的builder参数。
4.至ReactRootView
中的createReactContextInBackground()
函数调用至runCreateReactContextOnNewThread
函数中线程的createReactContext()
函数。内部则会完成创建ReactApplicationContext
对象并且绑定CatalystInstance
、三大线程以及Application Context
。
5.调用CatalystInstance
对象中的runJSBundle()
函数,完成JSBundle加载,,这里也完成了大部分功能的加载:构建JS环境等功能。
6.最后调用setupReactContext()
函数加载页面,通过attachRootViewToInstance()
函数调用的runApplication()
来完成。
二、CatalystInstance
CatalystInstance
CatalystInstance
为接口,他的实现类为CatalystInstanceImpl
。以下为其构造函数。private CatalystInstanceImpl(
final ReactQueueConfigurationSpec reactQueueConfigurationSpec,
final JavaScriptExecutor jsExecutor,
final NativeModuleRegistry nativeModuleRegistry,
final JSBundleLoader jsBundleLoader,
NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler) {
Log.d(ReactConstants.TAG, "Initializing React Xplat Bridge.");
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "createCatalystInstanceImpl");
mHybridData = initHybrid();
// 创建三大线程,内部包括,UI线程,Native线程,JS线程
mReactQueueConfiguration =
ReactQueueConfigurationImpl.create(
reactQueueConfigurationSpec, new NativeExceptionHandler());
mBridgeIdleListeners = new CopyOnWriteArrayList<>();
mNativeModuleRegistry = nativeModuleRegistry;
// JS Module注册表。
mJSModuleRegistry = new JavaScriptModuleRegistry();
mJSBundleLoader = jsBundleLoader;
mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler;
mNativeModulesQueueThread = mReactQueueConfiguration.getNativeModulesQueueThread();
mTraceListener = new JSProfilerTraceListener(this);
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
Log.d(ReactConstants.TAG, "Initializing React Xplat Bridge before initializeBridge");
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "initializeCxxBridge");
// 调用native接口创建通信桥
initializeBridge(
new BridgeCallback(this),
jsExecutor,
mReactQueueConfiguration.getJSQueueThread(),
mNativeModulesQueueThread,
mNativeModuleRegistry.getJavaModules(this),
mNativeModuleRegistry.getCxxModules());
Log.d(ReactConstants.TAG, "Initializing React Xplat Bridge after initializeBridge");
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
mJavaScriptContextHolder = new JavaScriptContextHolder(getJavaScriptContext());
}
上面重要的一部分就是ReactQueueConfiguration
对象创建。ReactQueueConfiguation
为接口,实现类为ReactQueueConfiguationImpl
。public interface ReactQueueConfiguration {
MessageQueueThread getUIQueueThread();
MessageQueueThread getNativeModulesQueueThread();
MessageQueueThread getJSQueueThread();
void destroy();
}
接口定义如上,其中的三个线程分别为UI线程,Native线程与JS线程。
UI线程:完成Android的UI线程及其相关工作。
Native线程:完成通信工作。
JS线程:完成JS的执行与渲染工作。
runJSBundle
继续runJSBundle()
函数调用。
首先需要看下上面的createReactContext
函数。 //创建CatalystInstanceImpl的Builder,它是三端通信的管理类
CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder()
.setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
//JS执行器
.setJSExecutor(jsExecutor)
//Java Module注册表
.setRegistry(nativeModuleRegistry)
//JS Bundle加载器
.setJSBundleLoader(jsBundleLoader)
//Java Exception处理器
.setNativeModuleCallExceptionHandler(exceptionHandler);
代码跳跃可以知道,JSBundleLoader
类用于创建本身对象,参数的类型为JSBundleLoaderDelegate
。而这里传进去的参数为CatalystInstanceImpl
环境本身,因为CatalystInstanceImpl
的实现接口有JSBundleLoaderDelegate
。public static JSBundleLoader createFileLoader(
final String fileName, final String assetUrl, final boolean loadSynchronously) {
return new JSBundleLoader() {
@Override
public String loadScript(JSBundleLoaderDelegate delegate) {
delegate.loadScriptFromFile(fileName, assetUrl, loadSynchronously);
return fileName;
}
};
}
实现的函数就在CatalystInstanceImpl
类中。@Override
public void loadScriptFromFile(String fileName, String sourceURL, boolean loadSynchronously) {
mSourceURL = sourceURL;
jniLoadScriptFromFile(fileName, sourceURL, loadSynchronously);
}
CatalystInstanceImpl.cpp
jni函数调用的位置就是CatalystInstanceImpl.cpp
的JNI层。void CatalystInstanceImpl::jniLoadScriptFromFile(const std::string& fileName,
const std::string& sourceURL,
bool loadSynchronously) {
if (Instance::isIndexedRAMBundle(fileName.c_str())) {
instance_->loadRAMBundleFromFile(fileName, sourceURL, loadSynchronously);
} else {
std::unique_ptr<const JSBigFileString> script;
RecoverableError::runRethrowingAsRecoverable<std::system_error>(
[&fileName, &script]() {
script = JSBigFileString::fromPath(fileName);
});
instance_->loadScriptFromString(std::move(script), sourceURL, loadSynchronously);
}
}
之后到Instance.cpp
中:void Instance::loadRAMBundleFromFile(const std::string& sourcePath, const std::string& sourceURL, bool loadSynchronously) {
auto bundle = folly::make_unique<JSIndexedRAMBundle>(sourcePath.c_str());
auto startupScript = bundle->getStartupCode();
auto registry = RAMBundleRegistry::multipleBundlesRegistry(std::move(bundle), JSIndexedRAMBundle::buildFactory());
loadRAMBundle(
std::move(registry),
std::move(startupScript),
sourceURL,
loadSynchronously);
}
void Instance::loadRAMBundle(std::unique_ptr<RAMBundleRegistry> bundleRegistry, std::unique_ptr<const JSBigString> startupScript, std::string startupScriptSourceURL, bool loadSynchronously) {
if (loadSynchronously) {
loadApplicationSync(std::move(bundleRegistry), std::move(startupScript),
std::move(startupScriptSourceURL));
} else {
loadApplication(std::move(bundleRegistry), std::move(startupScript),
std::move(startupScriptSourceURL));
}
}
void Instance::loadApplication(std::unique_ptr<RAMBundleRegistry> bundleRegistry,
std::unique_ptr<const JSBigString> string,
std::string sourceURL) {
callback_->incrementPendingJSCalls();
SystraceSection s("Instance::loadApplication", "sourceURL",
sourceURL);
nativeToJsBridge_->loadApplication(std::move(bundleRegistry), std::move(string),
std::move(sourceURL));
}
最后可以看到最终调用的是jnc层的loadApplication
函数,并最后通过JSExecutor
来与JS进行通信。
上述有点绕
整体调用如下,从runJSBundle()
开始:
1.调用至
CatalystInstanceImpl
中并调用JSBundleLoader
类中的JSBundleLoaderDelegate()
函数,但是该函数的实现确实在CatalystInstanceImpl
类中。
2.通过CatalystInstanceImpl
中实现的JSBundleLoaderDelegate()
函数,我们进入了JNI层CatalystinstanceImpl.cpp
文件,并调用至jniLoadScriptFromFile
进入JNI层。
3.最后调用至NativeToJsBridge.cpp
,看名字就知道,这个是从Native层进入JS层的重要类。这个类中的loadApplicationScript()
函数进入JSExecutor
类,这个类真正连接了JS层。
4.找到MessageQueue.js
类,这里就是上面native层进入js层的通信类。调用flushedQueue()
函数。完成整体的启动过程。
C++ 与 JS 中间层
上面注意调用的flush()
函数完成通信至MessageQueue.js
。
其中,这样的通信函数共有四个(MessageQueue.js中):
callFunctionReturnFlushedQueue()
invokeCallbackAndReturnFlushedQueue()
flushedQueue()
callFunctionReturnResultAndFlushedQueue()
完成这个的注册是由JSIExecutor
中的bindBridge()
函数完成,会从__fbBatchedBridge
对象中取出的上面四个函数。
他们分别存在C++层中一下四个参数:
callFunctionReturnFlushedQueue_
invokeCallbackAndReturnFlushedQueue_
flushedQueue_
callFunctionReturnResultAndFlushedQueue_
这样使得C++可以调用这四个函数,贯穿通信。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_ =
batchedBridge.getPropertyAsFunction(*runtime_, "flushedQueue");
callFunctionReturnResultAndFlushedQueue_ =
batchedBridge.getPropertyAsFunction(
*runtime_, "callFunctionReturnResultAndFlushedQueue");
});
}
这里开始就是进入MessageQueue.js
运行代码。
三、ReactRootView
上面的过程从ReactActivity
开始一直运行到MessageQueue.js
,过程中的createReactContext()
函数为分界点。之后就是调用setupReactContext()
函数。
private void setupReactContext(final ReactApplicationContext reactContext) {
...
synchronized (mAttachedReactRoots) {
...
// NativeModule初始化
catalystInstance.initialize();
// 绑定ReactContext
mDevSupportManager.onNewReactContextCreated(reactContext);
// 注册内存压力通知
mMemoryPressureRouter.addMemoryPressureListener(catalystInstance);
moveReactContextToCurrentLifecycleState();
ReactMarker.logMarker(ATTACH_MEASURED_ROOT_VIEWS_START);
// 将ReactRootView与CatalystInstance绑定
for (ReactRoot reactRoot : mAttachedReactRoots) {
attachRootViewToInstance(reactRoot);
}
ReactMarker.logMarker(ATTACH_MEASURED_ROOT_VIEWS_END);
}
...
}
private void attachRootViewToInstance(final ReactRoot reactRoot) {
UIManager uiManager = UIManagerHelper.getUIManager(mCurrentReactContext, reactRoot.getUIManagerType());
@Nullable Bundle initialProperties = reactRoot.getAppProperties();
// 将ReactRootView作为根布局
final int rootTag = uiManager.addRootView(reactRoot.getRootViewGroup(), initialProperties == null ? new WritableNativeMap() : Arguments.fromBundle(initialProperties), reactRoot.getInitialUITemplate());
reactRoot.setRootViewTag(rootTag);
...
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 {
reactRoot.runApplication();
}
}
这里定义最重要的页面工作,将ReactRootView作为根布局,并且会执行runApplication()
来进入JS层页面。
|
这里展示的部分代码,调用AppRegistry.js
内部的runApplication()
函数来完成JS层页面的渲染。
最终转换成Native层UI现实在手机上。