ReactNative TurboModule(3)

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 &params) {
    // 详见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 &params) {
    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 &params)
    : 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。

相关推荐
码农老起4 分钟前
掌握 React:组件化开发与性能优化的实战指南
react.js·前端框架
鸿蒙自习室4 分钟前
鸿蒙UI开发——组件滤镜效果
开发语言·前端·javascript
前端没钱37 分钟前
从 Vue 迈向 React:平滑过渡与关键注意点全解析
前端·vue.js·react.js
汪洪墩41 分钟前
【Mars3d】设置backgroundImage、map.scene.skyBox、backgroundImage来回切换
开发语言·javascript·python·ecmascript·webgl·cesium
居居飒1 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
我曾经是个程序员1 小时前
鸿蒙学习记录
开发语言·前端·javascript
羊小猪~~1 小时前
前端入门之VUE--ajax、vuex、router,最后的前端总结
前端·javascript·css·vue.js·vscode·ajax·html5
2401_857600953 小时前
基于 SSM 框架 Vue 电脑测评系统:赋能电脑品质鉴定
前端·javascript·vue.js
天之涯上上3 小时前
Pinia 是一个专为 Vue.js 3 设计的状态管理库
前端·javascript·vue.js
高山我梦口香糖4 小时前
[react] <NavLink>自带激活属性
前端·javascript·react.js