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。

相关推荐
Monly212 分钟前
JS:JSON操作
前端·javascript·json
Patience to do10 分钟前
Android Studio项目(算法计算器)
android·算法·android studio
觉醒法师1 小时前
HarmonyOS开发 - 本地持久化之实现LocalStorage支持多实例
前端·javascript·华为·typescript·harmonyos
w风雨无阻w2 小时前
Vue3 学习笔记(十一)Vue生命周期
javascript·vue.js·前端框架·vue3
清清ww2 小时前
【vue】13.深入理解递归组件
前端·javascript·vue.js
清清ww2 小时前
【vue】09.computer和watch的使用
前端·javascript·vue.js
你不讲 wood2 小时前
使用 Axios 上传大文件分片上传
开发语言·前端·javascript·node.js·html·html5
我又来搬代码了3 小时前
【Android】使用TextView实现按钮开关代替Switch开关
android
清灵xmf4 小时前
UI 组件的二次封装
前端·javascript·vue.js·element-plus
x原力觉醒5 小时前
uniapp跨域问题,在开发环境中配置
javascript·vue.js·uni-app