ReactNative TurboModule
简述
ReactNative新架构的两个核心支柱是TurboModule和Fabric渲染器,前者的功能是提供一个Native的模块,比如蓝牙之类的,后者则是提供一个自定义Native UI组件的能力,ReactNative本身虽然提供了非常多的组件,但是如果想要实现像Android自定义View一些复杂的组件UI效果,就需要自己定义Fabric组件,其实他们的核心都是通过jsi实现js和Native通信,然后在Android上则是通过jni实现Java和C++通信,最终达到js和Java层通信的效果,TurboModule和Fabric只是提供的接口不同,流程不同。
我们这一节先来了解一下TurboModule,TurboModule的逻辑相较于Fabric更加简单一些,所以先从TurboModule开始学习。
关于TurboModule的使用ReactNative官网上有详细的流程,我们就不过多介绍了,主要来介绍一下TurboModule的组件做了什么,怎么样实现JS和Java通信的。
Demo
我们自己定义一个TurboModule,然后基于这个TurboModule来介绍它的原理。
我们定义一个js文件,输出一个TurboModule,然后使用Codegen来生产脚手架。
Codegen的作用类似于aidl,帮助我们生成一些固定格式的代码,只是格式上和aidl不一样。
// @flow
import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport';
import { TurboModuleRegistry } from 'react-native';
export interface Spec extends TurboModule {
add(a: number, b: number): Promise<number>;
}
export default (TurboModuleRegistry.get<Spec>(
'RTNTurboTest'
): ?Spec);
我们来看看生成的文件,其中这里大多数文件都是没有用到的,如EventEmitters,Props,ShadowNode,State都没有用到,这些都是给Fabric使用的,映射JS层UI属性之类的,所以才说TurboModule的框架比Fabric更加简单,这些后续我们在介绍Fabric时会再介绍一下。
这里我们先来看NativeTurboTestSpec,我们最终的实现就是需要通过继承这个类,然后实现add方法,然后脚手架以及TurboModule框架帮助我们做的事情就是后续我们可以直接在JS中调用add方法,最终就会调用到我们实现的NativeTurboTestSpec子类的add方法中。
所以接下来我们要分析的就是ReactNative是怎么做到这个JS调用add最终调用到Java层的add中去的。
public abstract class NativeTurboTestSpec extends ReactContextBaseJavaModule implements TurboModule {
public static final String NAME = "RTNTurboTest";
public NativeTurboTestSpec(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public @Nonnull String getName() {
return NAME;
}
// 需要业务实现
@ReactMethod
@DoNotStrip
public abstract void add(double a, double b, Promise promise);
}
加载流程
在上一章介绍应用启动的流程中我们提到过,ReactInstance是React在Java侧最重要的管理类,加载TurboModule的包其实也由ReactInstance在构造函数中处理的。
我们接着上一章2.9,来看ReactInstance的构造函数。
1.1 ReactInstance
我们省略其他代码,只看TurboModule相关的逻辑。
/* package */ ReactInstance(
BridgelessReactContext bridgelessReactContext,
ReactHostDelegate delegate,
ComponentFactory componentFactory,
DevSupportManager devSupportManager,
QueueThreadExceptionHandler exceptionHandler,
boolean useDevSupport,
@Nullable ReactHostInspectorTarget reactHostInspectorTarget) {
// ...
mReactPackages = new ArrayList<>();
// 添加React的核心package,这些事ReactNative自己的TurboModule
mReactPackages.add(
new CoreReactPackage(
bridgelessReactContext.getDevSupportManager(),
bridgelessReactContext.getDefaultHardwareBackBtnHandler()));
if (useDevSupport) {
// 如果是debug模式
mReactPackages.add(new DebugCorePackage());
}
// 调用ReactHostDelegate的getReactPackages获取其他的ReactPackages
// 这个方法最终会调用Applcation里面定义的reactNativeHost匿名内部类的getReactPackages,详见1.1.1
mReactPackages.addAll(mDelegate.getReactPackages());
TurboModuleManagerDelegate turboModuleManagerDelegate =
mDelegate
// 这里获取的build是DefaultTurboModuleManagerDelegate.Builder()
.getTurboModuleManagerDelegateBuilder()
.setPackages(mReactPackages)
.setReactApplicationContext(mBridgelessReactContext)
// 详见1.2
.build();
RuntimeExecutor unbufferedRuntimeExecutor = getUnbufferedRuntimeExecutor();
// 构造TurboModuleManager,TurboModuleManager持有turboModuleManagerDelegate,就可以通过turboModuleManagerDelegate来管理所有的Package。
// 详见1.6
mTurboModuleManager =
new TurboModuleManager(
// Use unbuffered RuntimeExecutor to install binding
unbufferedRuntimeExecutor,
turboModuleManagerDelegate,
getJSCallInvokerHolder(),
getNativeMethodCallInvokerHolder());
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
// ...
}
1.1.1 ReactHostDelegate.getReactPackages
调用PackageList.getPackages 获取需要添加的包。
override val reactNativeHost: ReactNativeHost =
object : DefaultReactNativeHost(this) {
override fun getPackages(): List<ReactPackage> =
// 调用PackageList获取packages,详见1.1.2
PackageList(this).packages.apply {
// Packages that cannot be autolinked yet can be added manually here, for example:
// add(MyReactNativePackage())
}
override fun getJSMainModuleName(): String = "index"
override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
}
1.1.2 PackageList.getPackages
TurboTestPackage是我们自己定义的Package,所有自己定义的包。不只是TurboMoudle,Fabric也是在这里添加的。
这里的代码是我们通过Codegen生成模块的时候自动添加的。
public ArrayList<ReactPackage> getPackages() {
return new ArrayList<>(Arrays.<ReactPackage>asList(
new MainReactPackage(mConfig),
new TurboTestPackage()
));
}
1.2 DefaultTurboModuleManagerDelegate.Builder.build
构造DefaultTurboModuleManagerDelegate
override fun build(
context: ReactApplicationContext,
packages: List<ReactPackage>
): DefaultTurboModuleManagerDelegate {
val cxxReactPackages = mutableListOf<CxxReactPackage>()
for (cxxReactPackageProvider in cxxReactPackageProviders) {
cxxReactPackages.add(cxxReactPackageProvider(context))
}
// 详见1.3
return DefaultTurboModuleManagerDelegate(context, packages, cxxReactPackages)
}
1.3 DefaultTurboModuleManagerDelegate
DefaultTurboModuleManagerDelegate是ReactPackageTurboModuleManagerDelegate的子类。
调用了initialize方法。
protected ReactPackageTurboModuleManagerDelegate(
ReactApplicationContext reactApplicationContext,
List<ReactPackage> packages,
HybridData hybridData) {
super(hybridData);
// 调用了initialize,详见1.4
initialize(reactApplicationContext, packages);
}
1.4 ReactPackageTurboModuleManagerDelegate.initialize
这里的逻辑主要是通过收集的ReactPackage的getReactModuleInfoProvider提供的Provider,来获取每个Package包函的Module的ModuleInfo,我们自定义TurboModule时,这个getReactModuleInfoProvider是需要我们自己来实现的。
这里还存储了moduleProvider,它会调用package的getModule,这个getModule也是我们自己定义的,是new Module对象的地方。
private void initialize(
ReactApplicationContext reactApplicationContext, List<ReactPackage> packages) {
final ReactApplicationContext applicationContext = reactApplicationContext;
// 遍历所有的ReactPackage
for (ReactPackage reactPackage : packages) {
if (reactPackage instanceof BaseReactPackage) {
// 如果是BaseReactPackage,需要加载Provider,获取ModuleInfo
// TurboReactPackage是BaseReactPackage的子类,所以也会走这里
final BaseReactPackage baseReactPackage = (BaseReactPackage) reactPackage;
// 这里构建的Provider会调用package的getModule,这个getModule也是我们自己定义的,是new Module对象的地方。
final ModuleProvider moduleProvider =
moduleName -> baseReactPackage.getModule(moduleName, applicationContext);
mModuleProviders.add(moduleProvider);
// 这里会获取对应的Package的ModuleInfos,如果是自定义的TurboModule,这个getReactModuleInfos是需要我们实现的。
// 这里我们以我们自定义的TurboTestModule为例来看看,详见1.5
mPackageModuleInfos.put(
moduleProvider, baseReactPackage.getReactModuleInfoProvider().getReactModuleInfos());
continue;
}
// ...
}
}
1.5 TurboTestPackage
这个是我们自己定义的TurboModule,这里的逻辑就是照着官网的指引文档写的,主要是提供了两个方法,getReactModuleInfoProvider和getModule。
到这里,ReactPackageTurboModuleManagerDelegate就已经持有了所有的TurboModule的Info,后续只需要通过ReactPackageTurboModuleManagerDelegate我们就可以根据ModuleName来调用getModule构造对应的Module,后面构造了TurboModuleManager,TurboModuleManager持有ReactPackageTurboModuleManagerDelegate,后续就可以通过TurboModuleManager来获取或者构造对应的Module。
public class TurboTestPackage extends TurboReactPackage {
@Nullable
@Override
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
if (name.equals(TurboTestModule.NAME)) {
return new TurboTestModule(reactContext);
} else {
return null;
}
}
@Override
public ReactModuleInfoProvider getReactModuleInfoProvider() {
return () -> {
final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
moduleInfos.put(
TurboTestModule.NAME,
new ReactModuleInfo(
TurboTestModule.NAME,
TurboTestModule.NAME,
false, // canOverrideExistingModule
false, // needsEagerInit
true, // hasConstants
false, // isCxxModule
true // isTurboModule
));
return moduleInfos;
};
}
}
接下来我们来看一下TurboModuleManager,这里有比较关键的和C++绑定的逻辑,因为ReactNative有非常多的java和C++通信的逻辑都是通过这样的Binding来实现的,所以这里我们来看一下这个流程。
1.6 TurboModuleManager
调用installJSIBindings来构建JSI的绑定,绑定后就可以实现从JS层-〉C++ -〉Java的调用。
public TurboModuleManager(
RuntimeExecutor runtimeExecutor,
@Nullable final TurboModuleManagerDelegate delegate,
CallInvokerHolder jsCallInvokerHolder,
NativeMethodCallInvokerHolder nativeMethodCallInvokerHolder) {
mDelegate = delegate;
mHybridData =
initHybrid(
runtimeExecutor,
(CallInvokerHolderImpl) jsCallInvokerHolder,
(NativeMethodCallInvokerHolderImpl) nativeMethodCallInvokerHolder,
delegate);
// 关联JSI,构建C++,Java和JS层通信,详见1.7
installJSIBindings(shouldEnableLegacyModuleInterop(), enableSyncVoidMethods());
mEagerInitModuleNames =
delegate == null ? new ArrayList<>() : delegate.getEagerInitModuleNames();
ModuleProvider nullProvider = moduleName -> null;
// 封装delegate,后续可以通过这个provider根据moduleName获取对应/构建的Module
mTurboModuleProvider =
delegate == null
? nullProvider
: moduleName -> (NativeModule) delegate.getModule(moduleName);
mLegacyModuleProvider =
delegate == null || !shouldEnableLegacyModuleInterop()
? nullProvider
: moduleName -> {
NativeModule nativeModule = delegate.getLegacyModule(moduleName);
if (nativeModule != null) {
// TurboModuleManagerDelegate.getLegacyModule must never return a TurboModule
Assertions.assertCondition(
!(nativeModule instanceof TurboModule),
"NativeModule \"" + moduleName + "\" is a TurboModule");
return nativeModule;
}
return null;
};
}
1.7 TurboModuleManager.installJSIBindings
这是一个native方法,调用到TurboModuleManager::installJSIBindings
void TurboModuleManager::installJSIBindings(
jni::alias_ref<jhybridobject> javaPart,
bool shouldCreateLegacyModules,
bool enableSyncVoidMethods) {
auto cxxPart = javaPart->cthis();
if (cxxPart == nullptr || !cxxPart->jsCallInvoker_) {
return; // Runtime doesn't exist when attached to Chrome debugger.
}
cxxPart->runtimeExecutor_([cxxPart,
javaPart = jni::make_global(javaPart),
shouldCreateLegacyModules,
enableSyncVoidMethods](jsi::Runtime& runtime) {
// 调用了TurboModuleBinding::install
TurboModuleBinding::install(
runtime,
// 这里构造的moduleProvider,后续通过moduleProvider来构造Module
cxxPart->createTurboModuleProvider(
javaPart, &runtime, enableSyncVoidMethods),
shouldCreateLegacyModules
? cxxPart->createLegacyModuleProvider(javaPart)
: nullptr);
});
}
1.8 TurboModuleBinding::install
通过JSI绑定了JS的一些全局变量。比如global.__turboModuleProxy。
void TurboModuleBinding::install(
jsi::Runtime& runtime,
TurboModuleProviderFunctionType&& moduleProvider,
TurboModuleProviderFunctionType&& legacyModuleProvider,
std::shared_ptr<LongLivedObjectCollection> longLivedObjectCollection) {
// 绑定global.__turboModuleProxy,后续可以通过JS global.__turboModuleProxy调用到这里构建的方法。
runtime.global().setProperty(
runtime,
"__turboModuleProxy",
jsi::Function::createFromHostFunction(
runtime,
jsi::PropNameID::forAscii(runtime, "__turboModuleProxy"),
1,
[binding = TurboModuleBinding(
runtime, std::move(moduleProvider), longLivedObjectCollection)](
jsi::Runtime& rt,
const jsi::Value& thisVal,
const jsi::Value* args,
size_t count) {
if (count < 1) {
throw std::invalid_argument(
"__turboModuleProxy must be called with at least 1 argument");
}
std::string moduleName = args[0].getString(rt).utf8(rt);
return binding.getModule(rt, moduleName);
}));
// 根据JS属性RN$Bridgeless 来判断是否需要绑定后续的属性。
if (runtime.global().hasProperty(runtime, "RN$Bridgeless")) {
bool rnTurboInterop = legacyModuleProvider != nullptr;
auto turboModuleBinding = legacyModuleProvider
? std::make_unique<TurboModuleBinding>(
runtime,
std::move(legacyModuleProvider),
longLivedObjectCollection)
: nullptr;
auto nativeModuleProxy = std::make_shared<BridgelessNativeModuleProxy>(
std::move(turboModuleBinding));
defineReadOnlyGlobal(
runtime, "RN$TurboInterop", jsi::Value(rnTurboInterop));
defineReadOnlyGlobal(
runtime,
"nativeModuleProxy",
jsi::Object::createFromHostObject(runtime, nativeModuleProxy));
}
}
调用和创建TurboModule流程
我们从我们定义的js文件开始。
2.1 NativeTurboTest.js
这个文件是我们自己定义的,也是根据官方文档指引写的。
调用了TurboModuleRegistry.get来构造export的Spec。
// @flow
import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport';
import { TurboModuleRegistry } from 'react-native';
export interface Spec extends TurboModule {
add(a: number, b: number): Promise<number>;
}
// 通过TurboModuleRegistry.get获取,详见1.2
export default (TurboModuleRegistry.get<Spec>(
'RTNTurboTest'
): ?Spec);
2.2 TurboModuleRegistry.get
export function get<T: TurboModule>(name: string): ?T {
// 详见2.3
return requireModule<T>(name);
}
2.3 requireModule
function requireModule<T: TurboModule>(name: string): ?T {
if (!isBridgeless() || isTurboModuleInteropEnabled()) {
// ... 旧的架构逻辑
}
// 新架构,通过turboModuleProxy来获取目标Module
if (turboModuleProxy != null) {
const module: ?T = turboModuleProxy(name);
if (module != null) {
if (shouldReportDebugInfo()) {
moduleLoadHistory.TurboModules.push(name);
}
return module;
}
}
// ...
}
2.4 turboModuleProxy
turboModuleProxy就是global.__turboModuleProxy,我们在1.8提到过,已经通过JSI将global.__turboModuleProxy和C++的方法绑定了。
const turboModuleProxy = global.__turboModuleProxy;
2.5 global.__turboModuleProxy
这里到C++层了,这里调用了TurboModuleBinding.getModule来获取Module。
void TurboModuleBinding::install(
jsi::Runtime& runtime,
TurboModuleProviderFunctionType&& moduleProvider,
TurboModuleProviderFunctionType&& legacyModuleProvider,
std::shared_ptr<LongLivedObjectCollection> longLivedObjectCollection) {
runtime.global().setProperty(
runtime,
"__turboModuleProxy",
jsi::Function::createFromHostFunction(
runtime,
jsi::PropNameID::forAscii(runtime, "__turboModuleProxy"),
1,
[binding = TurboModuleBinding(
// global.__turboModuleProxy方法会通过JSI到这里。
runtime, std::move(moduleProvider), longLivedObjectCollection)](
jsi::Runtime& rt,
const jsi::Value& thisVal,
const jsi::Value* args,
size_t count) {
if (count < 1) {
throw std::invalid_argument(
"__turboModuleProxy must be called with at least 1 argument");
}
std::string moduleName = args[0].getString(rt).utf8(rt);
// 调用了getModule来获取Module,详见2.6
return binding.getModule(rt, moduleName);
}));
// ...
}
2.6 TurboModuleBinding::getModule
这里通过moduleProvider_来构造Module,这里的moduleProvider_是1.7通过cxxPart->createTurboModuleProvider构造的。
获取到Module后,Module里面有一个jsRepresentation_,这个jsRepresentation_是一个类似于句柄的东西,给JS层使用的,如果用过jni的话一般Java层会持有一个C++层的地址作为句柄,这里也是类似。
jsi::Value TurboModuleBinding::getModule(
jsi::Runtime& runtime,
const std::string& moduleName) const {
std::shared_ptr<TurboModule> module;
{
SystraceSection s(
"TurboModuleBinding::moduleProvider", "module", moduleName);
// 这里moduleProvider_是1.7通过cxxPart->createTurboModuleProvider构造的,详见2.7
module = moduleProvider_(moduleName);
}
if (module) {
// 这里获取Module的jsRepresentation_,这个类似于句柄,给JS层使用的,如果用过jni的话一般Java层会持有一个C++层的地址作为句柄,这里也是类似。
auto& weakJsRepresentation = module->jsRepresentation_;
if (weakJsRepresentation) {
auto jsRepresentation = weakJsRepresentation->lock(runtime);
if (!jsRepresentation.isUndefined()) {
return jsRepresentation;
}
}
jsi::Object jsRepresentation(runtime);
weakJsRepresentation =
std::make_unique<jsi::WeakObject>(runtime, jsRepresentation);
auto hostObject =
jsi::Object::createFromHostObject(runtime, std::move(module));
jsRepresentation.setProperty(runtime, "__proto__", std::move(hostObject));
return jsRepresentation;
} else {
return jsi::Value::null();
}
}
2.7 TurboModuleManager::createTurboModuleProvider
TurboModule分非常多种类,JavaModule,CxxModule,然后由于要兼容旧架构,还有leacyModule,会根据module不同的类型使用不同的方法来创建不同的Module,但是其实最终调用的方法是一样的。
这里我们就跟JavaModule的逻辑,构建了Java层的getTurboJavaModule方法并调用,ReactNative中java和C++的交互和jni看起来不太一样,其实是他们对jni又做了一次封装。(不得不说写前端的人非常喜欢框架)
delegate->cthis()->getTurboModule是绑定C++逻辑的,就是在这里和我们Codegen生成的脚手架关联,我们到第三小节来介绍这个。
TurboModuleProviderFunctionType TurboModuleManager::createTurboModuleProvider(
jni::alias_ref<jhybridobject> javaPart,
jsi::Runtime* runtime,
bool enableSyncVoidMethods) {
return [turboModuleCache_ = std::weak_ptr<ModuleCache>(turboModuleCache_),
runtime,
jsCallInvoker_ = std::weak_ptr<CallInvoker>(jsCallInvoker_),
nativeMethodCallInvoker_ =
std::weak_ptr<NativeMethodCallInvoker>(nativeMethodCallInvoker_),
weakDelegate = jni::make_weak(delegate_),
weakJavaPart = jni::make_weak(javaPart),
enableSyncVoidMethods](
const std::string& name) -> std::shared_ptr<TurboModule> {
// ...
// 先从缓存里查找是否存在对应name的Module
auto turboModuleLookup = turboModuleCache->find(name);
if (turboModuleLookup != turboModuleCache->end()) {
TurboModulePerfLogger::moduleJSRequireBeginningCacheHit(moduleName);
TurboModulePerfLogger::moduleJSRequireBeginningEnd(moduleName);
return turboModuleLookup->second;
}
TurboModulePerfLogger::moduleJSRequireBeginningEnd(moduleName);
// 通过delegate的getTurboModule构建对应Module
auto cxxModule = delegate->cthis()->getTurboModule(name, jsCallInvoker);
if (cxxModule) {
turboModuleCache->insert({name, cxxModule});
return cxxModule;
}
// 从GlobalModuleMap中查找是否存在对应的Module
auto& cxxTurboModuleMapProvider = globalExportedCxxTurboModuleMap();
auto it = cxxTurboModuleMapProvider.find(name);
if (it != cxxTurboModuleMapProvider.end()) {
auto turboModule = it->second(jsCallInvoker);
turboModuleCache->insert({name, turboModule});
return turboModule;
}
// 如果是legacyCxxModule,则通过getTurboLegacyCxxModule来获取
// legacyCxxModule是适配旧架构用的。
static auto getTurboLegacyCxxModule =
javaPart->getClass()
->getMethod<jni::alias_ref<CxxModuleWrapper::javaobject>(
const std::string&)>("getTurboLegacyCxxModule");
auto legacyCxxModule = getTurboLegacyCxxModule(javaPart.get(), name);
if (legacyCxxModule) {
TurboModulePerfLogger::moduleJSRequireEndingStart(moduleName);
auto turboModule = std::make_shared<react::TurboCxxModule>(
legacyCxxModule->cthis()->getModule(), jsCallInvoker);
turboModuleCache->insert({name, turboModule});
TurboModulePerfLogger::moduleJSRequireEndingEnd(moduleName);
return turboModule;
}
// 正常的JavaTruboModule,通过getTurboJavaModule来构建,这里getTurboJavaModule就是Java层的getTurboJavaModule方法了,详见2.8
static auto getTurboJavaModule =
javaPart->getClass()
->getMethod<jni::alias_ref<JTurboModule>(const std::string&)>(
"getTurboJavaModule");
auto moduleInstance = getTurboJavaModule(javaPart.get(), name);
if (moduleInstance) {
TurboModulePerfLogger::moduleJSRequireEndingStart(moduleName);
JavaTurboModule::InitParams params = {
.moduleName = name,
.instance = moduleInstance,
.jsInvoker = jsCallInvoker,
.nativeMethodCallInvoker = nativeMethodCallInvoker,
.shouldVoidMethodsExecuteSync = enableSyncVoidMethods};
// 详见3.1
auto turboModule = delegate->cthis()->getTurboModule(name, params);
if (moduleInstance->isInstanceOf(
JTurboModuleWithJSIBindings::javaClassStatic())) {
static auto getBindingsInstaller =
JTurboModuleWithJSIBindings::javaClassStatic()
->getMethod<BindingsInstallerHolder::javaobject()>(
"getBindingsInstaller");
auto installer = getBindingsInstaller(moduleInstance);
if (installer) {
// 详见
installer->cthis()->installBindings(*runtime);
}
}
// 将新构造的turboModule插入缓存
turboModuleCache->insert({name, turboModule});
TurboModulePerfLogger::moduleJSRequireEndingEnd(moduleName);
return turboModule;
}
return nullptr;
};
}
2.8 TurboModuleManager.getTurboJavaModule
调用了getModule来获取Module。
private TurboModule getTurboJavaModule(String moduleName) {
if (shouldRouteTurboModulesThroughLegacyModuleInterop()) {
return null;
}
if (!isTurboModule(moduleName)) {
return null;
}
// 调用了getModule,其实其他什么CxxModule最终也是调用这个方法来获取Module的,只是在返回值判断有效性的时候有所差异。
// 详见2.9
final NativeModule module = getModule(moduleName);
return !(module instanceof CxxModuleWrapper) && module instanceof TurboModule
? (TurboModule) module
: null;
}
2.9 TurboModuleManager.getModule
主要就是调用了getOrCreateModule来获取/创建Module,其他的就是一个缓存逻辑,只创建一次,后续使用之前创建的。
public NativeModule getModule(String moduleName) {
ModuleHolder moduleHolder;
synchronized (mModuleCleanupLock) {
if (mModuleCleanupStarted) {
// ...
return null;
}
// 这里是一个缓存逻辑
if (!mModuleHolders.containsKey(moduleName)) {
mModuleHolders.put(moduleName, new ModuleHolder());
}
moduleHolder = mModuleHolders.get(moduleName);
}
TurboModulePerfLogger.moduleCreateStart(moduleName, moduleHolder.getModuleId());
NativeModule module = getOrCreateModule(moduleName, moduleHolder, true);
if (module != null) {
TurboModulePerfLogger.moduleCreateEnd(moduleName, moduleHolder.getModuleId());
} else {
TurboModulePerfLogger.moduleCreateFail(moduleName, moduleHolder.getModuleId());
}
return module;
}
2.10 TurboModuleManager.getOrCreateModule
@Nullable
private NativeModule getOrCreateModule(
String moduleName, @NonNull ModuleHolder moduleHolder, boolean shouldPerfLog) {
boolean shouldCreateModule = false;
synchronized (moduleHolder) {
// 如果有缓存,就直接返回
if (moduleHolder.isDoneCreatingModule()) {
if (shouldPerfLog) {
TurboModulePerfLogger.moduleCreateCacheHit(moduleName, moduleHolder.getModuleId());
}
return moduleHolder.getModule();
}
if (!moduleHolder.isCreatingModule()) {
// Only one thread gets here
shouldCreateModule = true;
moduleHolder.startCreatingModule();
}
}
// 需要新建Module
if (shouldCreateModule) {
TurboModulePerfLogger.moduleCreateConstructStart(moduleName, moduleHolder.getModuleId());
// 这个mTurboModuleProvider是1.6构造函数时候创建的
// 最终是调用delegate.getModule(moduleName),详见2.11
NativeModule nativeModule = mTurboModuleProvider.getModule(moduleName);
if (nativeModule == null) {
nativeModule = mLegacyModuleProvider.getModule(moduleName);
}
TurboModulePerfLogger.moduleCreateConstructEnd(moduleName, moduleHolder.getModuleId());
TurboModulePerfLogger.moduleCreateSetUpStart(moduleName, moduleHolder.getModuleId());
if (nativeModule != null) {
synchronized (moduleHolder) {
moduleHolder.setModule(nativeModule);
}
nativeModule.initialize();
} else {
// ...
}
TurboModulePerfLogger.moduleCreateSetUpEnd(moduleName, moduleHolder.getModuleId());
synchronized (moduleHolder) {
moduleHolder.endCreatingModule();
moduleHolder.notifyAll();
}
return nativeModule;
}
synchronized (moduleHolder) {
boolean wasInterrupted = false;
while (moduleHolder.isCreatingModule()) {
try {
// Wait until TurboModule is created and initialized
moduleHolder.wait();
} catch (InterruptedException e) {
wasInterrupted = true;
}
}
if (wasInterrupted) {
/*
* TurboModules should ideally be quick to create and initialize. Therefore,
* we wait until the TurboModule is done initializing before re-interrupting the
* current thread.
*/
Thread.currentThread().interrupt();
}
return moduleHolder.getModule();
}
}
2.11 ReactPackageTurboModuleManagerDelegate.getModule
这里会遍历mModuleProviders,mModuleProviders里的ModuleProvider是我们1.4构建的,调用package的getModule。
package的getModule见1.5,我们自定义的TurboTestPackage会返回一个TurboTestModule。
到这加载流程就完成了。
public TurboModule getModule(String moduleName) {
NativeModule resolvedModule = null;
// 这里的mModuleProviders是1.4构建的,会调用每个package的getModule方法,而package的getMoudle是我们自己实现的
// 见1.5 TurboTestModule,我们会在getModule返回一个TurboTestModule实例。
for (final ModuleProvider moduleProvider : mModuleProviders) {
final ReactModuleInfo moduleInfo = mPackageModuleInfos.get(moduleProvider).get(moduleName);
if (moduleInfo != null
&& moduleInfo.isTurboModule()
&& (resolvedModule == null || moduleInfo.canOverrideExistingModule())) {
final NativeModule module = moduleProvider.getModule(moduleName);
if (module != null) {
resolvedModule = module;
}
}
}
boolean isLegacyModule = !(resolvedModule instanceof TurboModule);
if (isLegacyModule) {
return null;
}
return (TurboModule) resolvedModule;
}
调用流程
接下来我们看一下在JS层获取对应的Module后怎么通过JS方法调用到对应Module的Java层。
在2.7小节的时候提到了,如果是JavaModule还会调用delegate->cthis()->getTurboModule来和脚手架进行关联,我们从这里开始。
3.1 DefaultTurboModuleManagerDelegate::getTurboModule
这里调用了javaModuleProvider来处理底层的逻辑。
std::shared_ptr<TurboModule> DefaultTurboModuleManagerDelegate::getTurboModule(
const std::string& name,
const JavaTurboModule::InitParams& params) {
// 详见3.2
auto moduleProvider = DefaultTurboModuleManagerDelegate::javaModuleProvider;
if (moduleProvider) {
if (auto resolvedModule = moduleProvider(name, params)) {
return resolvedModule;
}
}
return nullptr;
}
3.2 javaModuleProvider
调用rncore_ModuleProvider加载rn和核心模块,调用了autolinking_ModuleProvider来加载我们自己定义的Module。
std::shared_ptr<TurboModule> javaModuleProvider(
const std::string& name,
const JavaTurboModule::InitParams& params) {
#ifdef REACT_NATIVE_APP_MODULE_PROVIDER
auto module = REACT_NATIVE_APP_MODULE_PROVIDER(name, params);
if (module != nullptr) {
return module;
}
#endif
// 这个是reactnative的core module
if (auto module = rncore_ModuleProvider(name, params)) {
return module;
}
// 我们自己定义的在这里,详见3.3
if (auto module = autolinking_ModuleProvider(name, params)) {
return module;
}
return nullptr;
}
3.3 autolinking_ModuleProvider
这个代码也是自动生成的,我们可以看到构建了一个RTNTurboTestSpec_ModuleProvider,这个是Codegen生成的脚手架,我们来看看。
std::shared_ptr<TurboModule> autolinking_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms) {
// 详见3.4
auto module_RTNTurboTestSpec = RTNTurboTestSpec_ModuleProvider(moduleName, params);
if (module_RTNTurboTestSpec != nullptr) {
return module_RTNTurboTestSpec;
}
return nullptr;
}
3.4 RTNTurboTestSpec_ModuleProvider
构建了一个NativeTurboTestSpecJSI类,这个类也是由Codegen生成的。
std::shared_ptr<TurboModule> RTNTurboTestSpec_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams ¶ms) {
if (moduleName == "RTNTurboTest") {
return std::make_shared<NativeTurboTestSpecJSI>(params);
}
return nullptr;
}
3.5 NativeTurboTestSpecJSI
这个类继承自JavaTurboModule,这里构造函数只是将方法名称和方法本身做一个映射,后续就可以通过methodMap_以及方法名找到对应的方法,__hostFunction_NativeTurboTestSpecJSI_add则是回调到java层最终的实现。
我们接着看一下父类JavaTurboModule的构造数(见3.6)。
NativeTurboTestSpecJSI::NativeTurboTestSpecJSI(const JavaTurboModule::InitParams ¶ms)
: JavaTurboModule(params) {
// __hostFunction_NativeTurboTestSpecJSI_add详见3.5.1
methodMap_["add"] = MethodMetadata {2, __hostFunction_NativeTurboTestSpecJSI_add};
}
3.5.1 __hostFunction_NativeTurboTestSpecJSI_add
static facebook::jsi::Value __hostFunction_NativeTurboTestSpecJSI_add(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
static jmethodID cachedMethodId = nullptr;
// 回调到java层的实现
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, PromiseKind, "add", "(DDLcom/facebook/react/bridge/Promise;)V", args, count, cachedMethodId);
}
3.6 JavaTurboModule
JavaTurboModule继承自TurboModule,TurboModule继承自facebook::jsi::HostObject,HostObject是JSI中的object,可以通过JSI将这个对象暴露给JS层。
从JS层比如调用turboModule.add,则会通过JSI调用到我们当前NativeTurboTestSpecJSI的get方法,这个get是HostObject的接口,由TurboModule实现,会遍历methodMap_找到对应的native方法来执行,这个在下一节我们来介绍JSI的时候会详细介绍。
JavaTurboModule::JavaTurboModule(const InitParams& params)
: TurboModule(params.moduleName, params.jsInvoker),
instance_(jni::make_global(params.instance)),
nativeMethodCallInvoker_(params.nativeMethodCallInvoker),
shouldVoidMethodsExecuteSync_(params.shouldVoidMethodsExecuteSync) {}
到这里我们就成功关联了JS层和java层的方法调用。
小结
本节我们介绍了TurboModule的加载流程,而且也介绍了Module中方法的绑定流程,讲述了如果从JS层调用方法最终调用到Java层,这个套逻辑是ReactNative最核心的逻辑,Fabric渲染器的核心也是通过JSI通信,只不过框架和接口的逻辑不太一样,且Fabric涉及更多的内容,Props,State等。
读完本节可能大家对JSI起到一个什么作用有了一些概念,下一节我们会深入的学习JSI。