2019-02-19
Instance 是 React Native 在 C++ 侧非常重要的一个类。初始化 Bridge、加载 Bundle 都通过它完成。在本文中,我们先来分析它在整个 React Native 框架中的位置。
Instance 实例是何时创建的呢?
Instance 是 CatalystInstanceImpl 的成员 instance_
,在 CatalystInstanceImpl 的构造函数中一同创建。
Instance 创建实例后,需要外界调用它的 initializeBridge 方法来初始化。这一步位于 CatalystInstanceImpl::initializeBridge 中。
我们来看 Instance::initializeBridge 方法,CatalystInstanceImpl::initializeBridge 外部调用代码为:
instance_->initializeBridge( folly::make_unique<JInstanceCallback>( callback, moduleMessageQueue_), jseh->getExecutorFactory(), folly::make_unique<JMessageQueueThread>(jsQueue), moduleRegistry_);
在 Instance::initializeBridge 的方法签名:
void Instance::initializeBridge( std::unique_ptr<InstanceCallback> callback, std::shared_ptr<JSExecutorFactory> jsef, std::shared_ptr<MessageQueueThread> jsQueue, std::shared_ptr<ModuleRegistry> moduleRegistry) {
我们可以对照来看。其内部逻辑是:
首先存下 callback 和 moduleRegistry:
callback_ = std::move(callback); moduleRegistry_ = std::move(moduleRegistry);
之后向 jsQueue 上扔了一个闭包:
jsQueue->runOnQueueSync([this, &jsef, jsQueue]() mutable { nativeToJsBridge_ = folly::make_unique<NativeToJsBridge>( jsef.get(), moduleRegistry_, jsQueue, callback_); std::lock_guard<std::mutex> lock(m_syncMutex); m_syncReady = true; m_syncCV.notify_all(); });
其中,主要操作是存下 nativeToJsBridge_
。
这样即完成了初始化操作。
上文中的 NativeToJsBridge 是什么呢?
它位于 ReactCommon/cxxreact/NativeToJsBridge.h,注解为:
这个类管理从 Native 代码到 JS 的调用。他还管理执行器和他们的线程。这里所有的方法都可以在任意线程中调用。
除了 loadApplicationScriptSync 之外,所有的 void 方法都要扔到 jsQueue 上运行,并立刻返回。
在注释中提到了执行器,我们快速回顾一下 Executor 是什么。它对应的类是 JSExecutor,这个类是一个基类,它的作用是隔离各种运行时(其实总共就一种)。
基于它派生出 JSCExecutor,它是 JavaScriptCore 的封装层,也就是 JS 引擎了。
我们再来看 NativeToJsBridge 的构造函数:
NativeToJsBridge::NativeToJsBridge( JSExecutorFactory* jsExecutorFactory, std::shared_ptr<ModuleRegistry> registry, std::shared_ptr<MessageQueueThread> jsQueue, std::shared_ptr<InstanceCallback> callback) : m_destroyed(std::make_shared<bool>(false)) , m_delegate(std::make_shared<JsToNativeBridge>(registry, callback)) , m_executor(jsExecutorFactory->createJSExecutor(m_delegate, jsQueue)) , m_executorMessageQueueThread(std::move(jsQueue)) {}
其中 m_executor
这行我们可以看出,NativeToJsBridge 从 Holder 中自己创建了一个 JS 运行时。
NativeToJsBridge 中各种方法则是基于运行时封装出的能力。
NativeToJsBridge 弄清楚后,我们回到 Instance。
Instance 将 NativeToJsBridge 实例存放在 nativeToJsBridge_
成员中。
Instance 基于 NativeToJsBridge 提供的 JS 运行时,提供了一下能力:
Instance 作为 CatalystInstanceImpl 的成员,CatalystInstanceImpl 是如何使用它的呢?
CatalystInstanceImpl::extendNativeModules:
moduleRegistry_->registerModules
CatalystInstanceImpl::jniSetSourceURL:
instance_->setSourceURL(sourceURL);
CatalystInstanceImpl::jniRegisterSegment:
instance_->registerBundle
CatalystInstanceImpl::jniLoadScriptFromAssets:
instance_->loadRAMBundle
在这里省略一些方法。因为已经足够看出,CatalystInstanceImpl 中大部分方法都是加载 JS bundle,与运行时打交道,而这些与运行时相关的具体操作,都代理封装在了 Instance 中。
在 CatalystInstanceImpl 中还有一个方法,即 CatalystInstanceImpl::getInstance(),外界可以通过它获取 Instance 实例。在外部都有哪些类使用到它呢?
找了一圈,原来并没有调用的地方。
至此我们可以得出 Instance 类的作用是做什么的了: