ReactNative TurboModule(3)

news2024/10/28 19:24:36

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。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2225632.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python 中 {} 是 set 还是 dict

先说结论&#xff1a; {} 是 dict 字典。 一、描述 在 Python 中&#xff0c;我们可以用如下&#xff0c;表示一个集合 set my_set {1, 2, 3, 4, 5, 6} 也可以用如下&#xff0c;表示一个字典 dict my_dict {1:10, 2:20, 3:30, 4:40} 不管是集合还是字典&#xff0c;都…

【Ubuntu20.04 Visual Studio Code安装】【VSCODE】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、打开VSCOE官网二、下载VSODE的Ubuntu版本三、安装VSCODE软件包四、导入工作空间(添加工作空间目录)五、安装插件&#xff1a;1.安装简体中文包2.安装ros插件…

NSSCTF刷题篇web部分

源码泄露 [FSCTF 2023]寻找蛛丝马迹 这个源码泄露&#xff0c;可以记录一下&#xff0c;涉及的知识点比较多 打开环境 查看源码&#xff0c; 第一段flag 乱码&#xff0c;恢复一下 乱码恢复网站&#xff1a;乱码恢复 (mytju.com) 剩下的就只说方法 http://node4.anna.nss…

python实现放烟花效果庆祝元旦

马上就要2025年元旦啦&#xff0c;提前祝大家新年快乐 完整代码下载地址&#xff1a;https://download.csdn.net/download/ture_mydream/89926458

uaGate SI——实现OT与IT的安全连接

对于许多制造商来说&#xff0c;诸如工业物联网&#xff08;IIoT&#xff09;、信息物理系统&#xff08;CPS&#xff09;和大数据等概念已经开始与其智能工厂的愿景紧密相连。智能工厂是将信息技术&#xff08;IT&#xff09;的数字世界与运营技术&#xff08;OT&#xff09;的…

H5的Canvas绘图——使用fabricjs绘制一个可多选的随机9宫格

&#x1f4e2;欢迎点赞 &#xff1a;&#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff0c;赐人玫瑰&#xff0c;手留余香&#xff01;&#x1f4e2;本文作者&#xff1a;由webmote 原创&#x1f4e2;作者格言&#xff1a;新的征程&#xff0c;最近一直被测试…

node升级package.json中的版本

由于项目使用时间过老&#xff0c;升级对应包版本&#xff0c;可以使用新功能 1.使用npm-check-updates这个工具&#xff0c;先全局安装 npm install -g npm-check-updates2.检查package.json中dependencies的最新版本 ncu3.更新dependencies到新版本 ncu -u也是一样的 npx…

微知SOP-定位Linux crash问题的几个常用方面和常用命令?

文章目录 1 背景2 问题描述和SOP2.1 进入目录2.2 安装crasn和vmlinux2.3 使用crash命令进入debug目录2.4 收集主要信息2.5 收集task关键信息2.6 查看堆栈信息2.7 使用反汇编查看crash所在行2.8 根据寄存器获取一些关键数据2.9 根据堆栈获取信息2.10 加载内核模块2.11 收集其他t…

宿舍管理新篇章:基于Spring Boot的系统开发

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

零基础学linux文件管理

目录 引言 基础知识 回顾C语言 fopen fclose 更改进程路径&#xff1a;chdir fwrite可以用来写入 sizeof字符串 C语言默认打开三个输入输出流 过渡到系统 系统调用&#xff1a;open “位字段”或“位掩码” open的使用 关闭文件&#xff1a;close 写入&#xff1…

【C++】继承与模板

继承 1.继承的概念 概念&#xff1a;继承(inheritace)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称之为派生类。继承呈现了面向对象程序设计的…

AI创作者与人类创作者的协作模式

公主请阅 1. AI创作者的崛起1.1 AI创作者的工作原理1.2 AI创作者的优势 2. 人类创作者的独特价值2.1 创造性与情感2.2 伦理与价值观2.3 文化与背景 3. AI与人类的协作模式3.1 协同创作3.2 内容编辑3.3 数据驱动的创作3.4 跨媒体协作 4. AI与人类协作的挑战4.1 技术局限性4.2 版…

Linux学习笔记 | sudo命令的基本使用

sudo命令 sudo 命令是 Unix 和 Linux 系统中用于执行需要超级用户权限&#xff08;即 root 权限&#xff09;操作的工具。它允许系统管理员授予某些用户&#xff08;或用户组&#xff09;以 root 或其他指定用户的权限来运行特定命令&#xff0c;而无需知道 root 用户的密码。…

在Java中,需要每120分钟刷新一次的`assetoken`,并且你想使用Redis作为缓存来存储和管理这个令牌

学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把手教你开发炫酷的vbs脚本制作(完善中……&#xff09; 4、牛逼哄哄的 IDEA编程利器技巧(编写中……&#xff09; 5、面经吐血整理的 面试技…

Uni-App-02

条件编译 条件编译概念 不同的运行平台终归有些专有的特性&#xff0c;无法实现跨平台完全兼容&#xff0c;例如&#xff1a;微信小程序导航栏右上角的关闭图标。 uni-app提供了一种“条件编译”机制&#xff0c;可以针对特定的平台编译执行特定的代码&#xff0c;否则不执行。…

高翔【自动驾驶与机器人中的SLAM技术】学习笔记(十二)拓展图优化库g2o(一)框架

【转载】理解图优化&#xff0c;一步步带你看懂g2o框架 文章来源&#xff1a;理解图优化&#xff0c;一步步带你看懂g2o框架 小白&#xff1a;师兄师兄&#xff0c;最近我在看SLAM的优化算法&#xff0c;有种方法叫“图优化”&#xff0c;以前学习算法的时候还有一个优化方法…

Spring Web MVC 入门

1. 什么是 Spring Web MVC Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架&#xff0c;从从⼀开始就包含在Spring框架中。它的 正式名称“SpringWebMVC”来⾃其源模块的名称(Spring-webmvc)&#xff0c;但它通常被称为"Spring MVC". 什么是Servlet呢? Ser…

OpenAI被爆12月发布其Orion AI模型!波兰“OFF”电台解雇所有记者,启用AI“主持人”|AI日报

文章推荐 Stability AI一口气推出3款图像生成模型系列&#xff01;升级版Claude 3.5 Sonnet能像人类一样操控电脑&#xff5c;AI日报 今日热点 据报道&#xff0c;OpenAI计划于12月发布其Orion AI模型 据The Verge昨日报道&#xff0c;OpenAI计划在今年12月之前发布其下一个…

ctfshow(171,172,173)--SQL注入--联合注入

Web171 进入靶场&#xff0c;是一个SQL查询界面&#xff1a; 审计&#xff1a; 查询语句如下&#xff1a; $sql "select username,password from user where username !flag and id ".$_GET[id]." limit 1;";语句功能从数据表user中查询username,pa…

MATLAB生态环境数据处理与分析

原文链接&#xff1a;MATLAB在生态环境数据处理与分析https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247624407&idx4&sn39c8119bba0797e6bf5cc35eea1c6767&chksmfa8da730cdfa2e266dac5221af101230d7ded29576a34856b31f736a89dbb2e3e481a5e94e8a&to…