React Native开发React Native开发经验集 reactnative

ReactNative源码分析 - 启动流程

2019-12-15  本文已影响0人  浮游lb

1.ReactNative源码分析 - 概述
2.ReactNative源码分析 - JavaScriptCore C语言篇
3.ReactNative源码分析 - 启动流程
4.ReactNative源码分析 - 通信机制
5.ReactNative源码分析 - 渲染原理

一、ReactNative类图

ReactNative类图.jpg

二、ReactNative启动流程简析

三、ReactNative启动流程详解

0.启动流程起点

ReactNative代码入口是:RCTRootView初始化函数initWithBridge: initialProperties:,用于实例化RCTRootView作为UIViewController的view。其中用传入RCTBridge,这便是启动流程的源头,启动完毕才正在执行JS模块AppRegistry runApplication,运行组件,开始渲染。

- (instancetype)initWithBridge:(RCTBridge *)bridge
                    moduleName:(NSString *)moduleName
             initialProperties:(NSDictionary *)initialProperties
{
   if (self = [super initWithFrame:CGRectZero]) {
    _bridge = bridge;
    _moduleName = moduleName;
    _appProperties = [initialProperties copy];
    ...
    [self bundleFinishedLoading:([_bridge batchedBridge] ?: _bridge)];
  }
  return self;
}

- (void)bundleFinishedLoading:(RCTBridge *)bridge
{
  ...
  [self runApplication:bridge];
  ...
}

- (void)runApplication:(RCTBridge *)bridge
{
  NSString *moduleName = _moduleName ?: @"";
  NSDictionary *appParameters = @{
    @"rootTag": _contentView.reactTag,
    @"initialProps": _appProperties ?: @{},
  };
  
  // (Native调用JS) 调用JS模块AppRegistry runApplication,运行组件
  [bridge enqueueJSCall:@"AppRegistry"
                 method:@"runApplication"
                   args:@[moduleName, appParameters]
             completion:NULL];
}

1.构建Native&JS通信表层Bridge

// RCTBridge.h

// 启动流程通知
RCT_EXTERN NSString *const RCTJavaScriptWillStartLoadingNotification;
RCT_EXTERN NSString *const RCTJavaScriptDidLoadNotification;
...
// 初始化
- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)delegate
                   launchOptions:(NSDictionary *)launchOptions;
...
// 调用JS模块函数
- (void)enqueueJSCall:(NSString *)moduleDotMethod args:(NSArray *)args;
- (void)enqueueJSCall:(NSString *)module method:(NSString *)method args:(NSArray *)args completion:(dispatch_block_t)completion
// RCTBridge.m
- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)delegate
                       bundleURL:(NSURL *)bundleURL
                  moduleProvider:(RCTBridgeModuleListProvider)block
                   launchOptions:(NSDictionary *)launchOptions
{
  if (self = [super init]) {
    _delegate = delegate;
    _bundleURL = bundleURL;
    _moduleProvider = block;
    _launchOptions = [launchOptions copy];
    
    [self setUp]; // 初始化batchedBridge
  }
  return self;
}

- (void)setUp
{
  Class bridgeClass = self.bridgeClass;
  _bundleURL = [RCTConvert NSURL:_bundleURL.absoluteString];
    ...
  // 构建batchedBridge(C++ Bridge)
  self.batchedBridge = [[bridgeClass alloc] initWithParentBridge:self];
  [self.batchedBridge start];
}

RCTCxxBridge初始化主要是创建一些标识位、原生模块容器等。接着执行start操作,这是启动流程的最为核心的地方,启动流程所有操作都从这里开始。

// RCTCxxBridge.mm
- (void)start
{
  // 2.创建常驻线程,开启runloop
  _jsThread = [[NSThread alloc] initWithTarget:[self class]
                                      selector:@selector(runRunLoop)
                                        object:nil];
  _jsThread.name = RCTJSThreadName;
  _jsThread.qualityOfService = NSOperationQualityOfServiceUserInteractive;
  [_jsThread start];

  dispatch_group_t prepareBridge = dispatch_group_create();

  // 3.加载自动注册的原生模块(创建原生模块描述对象、构造原生模块实例)
  (void)[self _initializeModules:RCTGetModuleClasses() withDispatchGroup:prepareBridge lazilyDiscovered:NO];
 
  // 4.js线程中初始化底层 _reactInstance 
  // 创建底层 _reactInstance实例
  _reactInstance.reset(new Instance);

  std::shared_ptr<JSExecutorFactory> executorFactory;
  executorFactory = std::make_shared<JSCExecutorFactory>(nullptr); // 生产环境工厂类 JSCExecutorFactory

  dispatch_group_enter(prepareBridge);
  [self ensureOnJavaScriptThread:^{
    // 主要初始化操作在initializeBridge中完成
    [weakSelf _initializeBridge:executorFactory];
    dispatch_group_leave(prepareBridge);
  }];

  // 5.加载 js bundle包(整包,异步加载)
  dispatch_group_enter(prepareBridge);
  __block NSData *sourceCode;
  [self loadSource:^(NSError *error, RCTSource *source) {
    if (error) {
      [weakSelf handleError:error];
    }
    sourceCode = source.data;
    dispatch_group_leave(prepareBridge);
  } onProgress:^(RCTLoadingProgress *progressData) { ... }];

  // 6.等待 需要在主线程创建的原生模块实例创建完毕、底层_reactInstance初始化完毕、 js bundle包加载完毕,执行js bundle
  dispatch_group_notify(prepareBridge, dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
    RCTCxxBridge *strongSelf = weakSelf;
    if (sourceCode && strongSelf.loading) {
      [strongSelf executeSourceCode:sourceCode sync:NO];
    }
  });
}

2.创建JS线程

JS线程:这是一个常驻线程,会一直存活,涉及RunLoop线程保活相关知识。启动过程中的很多初始化操作、Native&JS通信、执行js bundle包都在该线程进行。

// RCTCxxBridge.mm
- (void)start
{
  // 2.创建常驻线程,开启runloop
  _jsThread = [[NSThread alloc] initWithTarget:[self class]
                                      selector:@selector(runRunLoop)
                                        object:nil];
  _jsThread.name = RCTJSThreadName;
  _jsThread.qualityOfService = NSOperationQualityOfServiceUserInteractive;
  [_jsThread start];
  ...
 }
 
 + (void)runRunLoop
{
  @autoreleasepool {
    pthread_setname_np([NSThread currentThread].name.UTF8String);

    // 添加事件源Source,避免退出RunLoop
    CFRunLoopSourceContext noSpinCtx = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
    CFRunLoopSourceRef noSpinSource = CFRunLoopSourceCreate(NULL, 0, &noSpinCtx);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), noSpinSource, kCFRunLoopDefaultMode);
    CFRelease(noSpinSource);

    // kCFRunLoopDefaultMode模式下启动RunLoop,永不退出
    while (kCFRunLoopRunStopped != CFRunLoopRunInMode(kCFRunLoopDefaultMode, ((NSDate *)[NSDate distantFuture]).timeIntervalSinceReferenceDate, NO)) {
      RCTAssert(NO, @"not reached assertion"); // runloop spun. that's bad.
    }
  }
}
// RCTCxxBridge.mm
- (void)ensureOnJavaScriptThread:(dispatch_block_t)block
{
  if ([NSThread currentThread] == _jsThread) {
    [self _tryAndHandleError:block];
  } else {
    [self performSelector:@selector(_tryAndHandleError:)
          onThread:_jsThread
          withObject:block
          waitUntilDone:NO];
  }
}

3.收集原生模块信息,构建原生模块实例

预编译操作流程截图.jpg
RCT_EXPORT_MODULE(TestManager) 

// 预处理后代码如下
extern void RCTRegisterModule(Class); 
+ (NSString *)moduleName {
    return @"TestManager";
}
+ (void)load {
    RCTRegisterModule(self);
}

RCT_EXPORT_MODULE宏替换结果如上,主要是:实现RCTBridgeModule协议函数+ (NSString *)moduleName返回原生模块名称,并重写+ (void)load函数,调用RCTRegisterModule()把类注册到原生模块类集合。通过函数RCTGetModuleClasses()可获取

// RCTBridge.m
// 原生模块表
static NSMutableArray<Class> *RCTModuleClasses;
// 原生模块表操作队列:保证读写安全(读写锁:多读一写,不同时读写)
static dispatch_queue_t RCTModuleClassesSyncQueue;
NSArray<Class> *RCTGetModuleClasses(void)
{
  __block NSArray<Class> *result;
  dispatch_sync(RCTModuleClassesSyncQueue, ^{
    result = [RCTModuleClasses copy];
  });
  return result;
}

void RCTRegisterModule(Class moduleClass)
{
  ...
  dispatch_barrier_async(RCTModuleClassesSyncQueue, ^{
    [RCTModuleClasses addObject:moduleClass];
  });
}

原生模块函数通过宏RCT_EXPORT_METHOD来导出,宏替换效果如下。可知该宏主要作用是:生成导出函数,并且生成一个以__rct_export__为前缀,加上当前行号列号作为函数名的类函数,该函数返回的结构体RCTMethodInfo包含了导出函数信息有 JS名、原生函数名、是否为同步函数。后序收集原生模块信息正是通过runtime扫描带__rct_export__前缀的函数,执行函数调用以获取导出函数信息。

RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(NSNumber *)secondsSinceUnixEpoch)
{
  NSDate *date = [RCTConvert NSDate:secondsSinceUnixEpoch];
  RCTLogInfo(@"Date : %@",date);
}

// 上述导出函数宏替换后如下
 + (const RCTMethodInfo *)__rct_export__390 {
   static RCTMethodInfo config = {
      "",
      "addEvent:(NSString *)name location:(NSString *)location date:(NSNumber *)secondsSinceUnixEpoch",
      NO,
   };
   return &config;
 }
 - (void)addEvent:(NSString *)name location:(NSString *)location date:(nonnull NSNumber *)secondsSinceUnixEpoch ;
 {
    NSDate *date = [RCTConvert NSDate:secondsSinceUnixEpoch];
    RCTLogInfo(@"Date : %@",date);
 }

初始化:RCTModuleData初始化仅需入原生模块类型moduleClass、bridge,但已足够构建原生模块实例并获取它的一切信息

// RCTModuleData.mm
- (instancetype)initWithModuleClass:(Class)moduleClass
                             bridge:(RCTBridge *)bridge
{
  // 初始化 moduleProvider,用于后面构建模块实例_instance
  return [self initWithModuleClass:moduleClass
                    moduleProvider:^id<RCTBridgeModule>{ return [moduleClass new]; }
                    bridge:bridge];
}

构建原生模块实例:使用c++互斥锁std::mutex保证实例的线程安全。unique_lock()函数,独占or等待互斥锁_instanceLock,当lock作用域结束时,自动释放锁。 {...} 为加锁区,作用是减小加锁区域。

// RCTModuleData.mm
- (void)setUpInstanceAndBridge {
  {  // 加锁区域
    std::unique_lock<std::mutex> lock(_instanceLock);
    if (!_setupComplete && _bridge.valid) {
      if (!_instance) {
        // 构建实例
        _instance = _moduleProvider ? _moduleProvider() : nil;
      }
      ....
      [self setBridgeForInstance];
    }
    [self setUpMethodQueue];
  }
  ...
}

// 配置原生模块实例bridge RCTCxxBridge
- (void)setBridgeForInstance
{
  if ([_instance respondsToSelector:@selector(bridge)] && _instance.bridge != _bridge) {
      [(id)_instance setValue:_bridge forKey:@"bridge"];
  }
}

获取导出函数:Runtime遍历原生模块类函数,找出以__rct_export__为前缀的并调用,以获取导出函数信息RCTMethodInfo,构造RCTBridgeMethod实例。RCTBridgeMethod实例是原生模块导出函数描述对象,包含导出函数信息,JS call Native最终由它来执行函数调用。

// RCTModuleData.mm
// 获取模块导出的方法
- (NSArray<id<RCTBridgeMethod>> *)methods
{
  if (!_methods) {
    NSMutableArray<id<RCTBridgeMethod>> *moduleMethods = [NSMutableArray new];

    // Runtime遍历原生模块类方法,找出以__rct_export__为浅醉的类方法
    unsigned int methodCount;
    Class cls = _moduleClass;
    while (cls && cls != [NSObject class] && cls != [NSProxy class]) {
      Method *methods = class_copyMethodList(object_getClass(cls), &methodCount);
      for (unsigned int i = 0; i < methodCount; i++) {
        Method method = methods[i];
        SEL selector = method_getName(method);
        if ([NSStringFromSelector(selector) hasPrefix:@"__rct_export__"]) {
          // 执行原生函数,获取导出函数信息
          IMP imp = method_getImplementation(method);
          auto exportedMethod = ((const RCTMethodInfo *(*)(id, SEL))imp)(_moduleClass, selector);
          id<RCTBridgeMethod> moduleMethod = [[RCTModuleMethod alloc] initWithExportedMethod:exportedMethod moduleClass:_moduleClass];
          [moduleMethods addObject:moduleMethod];
        }
      }

      free(methods);
      cls = class_getSuperclass(cls);
    }
    _methods = [moduleMethods copy];
  }
  return _methods;
}
// RCTCxxBridge.mm
- (void)start
{
   ···
  dispatch_group_t prepareBridge = dispatch_group_create();

  // 3.加载自动注册的原生模块(创建原生模块描述对象、构造原生模块实例)

  // 加载手动导出的原生模块
  [self registerExtraModules];
  // 加载自动注册的原生模块(创建原生模块描述对象、构造原生模块实例)
  (void)[self _initializeModules:RCTGetModuleClasses() withDispatchGroup:prepareBridge lazilyDiscovered:NO];
  // 加载调试模式所需原生模块
  [self registerExtraLazyModules];
··· 
}

- (NSArray<RCTModuleData *> *)_initializeModules:(NSArray<id<RCTBridgeModule>> *)modules
                               withDispatchGroup:(dispatch_group_t)dispatchGroup
                                lazilyDiscovered:(BOOL)lazilyDiscovered
{
    // 创建原生模块描述对象
    NSArray<RCTModuleData *> *moduleDataById = [self _registerModulesForClasses:modules lazilyDiscovered:lazilyDiscovered];
    ...
    // 创建 自动注册的原生模块实例
    [self _prepareModulesWithDispatchGroup:dispatchGroup];
}

- (NSArray<RCTModuleData *> *)_registerModulesForClasses:(NSArray<Class> *)moduleClasses
                                        lazilyDiscovered:(BOOL)lazilyDiscovered
{
  NSArray *moduleClassesCopy = [moduleClasses copy];
  NSMutableArray<RCTModuleData *> *moduleDataByID = [NSMutableArray arrayWithCapacity:moduleClassesCopy.count];
  for (Class moduleClass in moduleClassesCopy) {
    ···
    // 创建原生模块描述对象,并存放到对应容器
    NSString *moduleName = RCTBridgeModuleNameForClass(moduleClass);
    moduleData = [[RCTModuleData alloc] initWithModuleClass:moduleClass bridge:self];
    _moduleDataByName[moduleName] = moduleData;
    [_moduleClassesByID addObject:moduleClass];
    [moduleDataByID addObject:moduleData];
  }
  [_moduleDataByID addObjectsFromArray:moduleDataByID];
}

- (void)_prepareModulesWithDispatchGroup:(dispatch_group_t)dispatchGroup
{
  for (RCTModuleData *moduleData in _moduleDataByID) {
    if (moduleData.requiresMainQueueSetup) {
      dispatch_block_t block = ^{
        if (self.valid && ![moduleData.moduleClass isSubclassOfClass:[RCTCxxModule class]]) {
          // 创建模块实例
          (void)[moduleData instance];
          // 收集模块导出常量
          [moduleData gatherConstants];
        }
      };

      if (RCTIsMainQueue()) {
        block();
      } else {
        if (dispatchGroup) {
          dispatch_group_async(dispatchGroup, dispatch_get_main_queue(), block);
        }
      }
    }
  }
}

注:触发原生模块实例化的线程无法保证。如果是在JS线程触发需要在主线程实例化的原生模块实例化,除非使用dispatch_sync同步函数派发实例化任务到主线程,否则不可以懒加载,但这种方式可能造成死锁(假设实例化任务在主线程发起…)。为此ReactNative使用GCD队列组,在加载js bundle的同时,在主线程构建原生模块实例,保证在执行js bundle之前,需要在主线程实例化的原生模块实例化完毕。

15760766355461.jpg

4.构建真正执行通信任务的底层Bridge

// RCTCxxBridge.mm
- (void)start
{
  ...
  // 4.在js线程中初始化底层 _reactInstance 
  
  // 创建底层 _reactInstance实例,主要初始化操作在是函数initializeBridge中完成
  _reactInstance.reset(new Instance);

  std::shared_ptr<JSExecutorFactory> executorFactory;
  executorFactory = std::make_shared<JSCExecutorFactory>(nullptr); // 生产环境工厂类 JSCExecutorFactory
    
  // JS线程 初始化底层Bridge
  dispatch_group_enter(prepareBridge);
  [self ensureOnJavaScriptThread:^{
    [weakSelf _initializeBridge:executorFactory];
    dispatch_group_leave(prepareBridge);
  }];
  ...
}

- (void)_initializeBridge:(std::shared_ptr<JSExecutorFactory>)executorFactory
{
  // 构建 _jsMessageThread
  __weak RCTCxxBridge *weakSelf = self;
  _jsMessageThread = std::make_shared<RCTMessageThread>([NSRunLoop currentRunLoop], ^(NSError *error) { ... });

  if (_reactInstance) {
    [self _initializeBridgeLocked:executorFactory];
  }
}

- (void)_initializeBridgeLocked:(std::shared_ptr<JSExecutorFactory>)executorFactory
{
  std::lock_guard<std::mutex> guard(_moduleRegistryLock);
  _reactInstance->initializeBridge(
                                   std::make_unique<RCTInstanceCallback>(self),
                                   executorFactory,
                                   _jsMessageThread,
                                   [self _buildModuleRegistryUnlocked]);
}

- (std::shared_ptr<ModuleRegistry>)_buildModuleRegistryUnlocked
{
  ModuleRegistry::ModuleNotFoundCallback moduleNotFoundCallback = ...
  auto registry = std::make_shared<ModuleRegistry>(
         createNativeModules(_moduleDataByID, self, _reactInstance),
         moduleNotFoundCallback);
  return registry;
}

Instance初始化函数initializeBridge,意味着已经到了ReactNative框架的公共层(提及框架的分层设计,ReactCommon目录为iOS/Android两端公共层),代码为纯C++。此处传参出现了几个新类型,在此一一解释


struct RCTInstanceCallback : public InstanceCallback {
  void onBatchComplete() override {
    [bridge_ partialBatchDidFlush];
    [bridge_ batchDidComplete];
  }
};

// RCTMessageThread.mm

// 往runloop中添加block任务
void RCTMessageThread::runAsync(std::function<void()> func) {
  CFRunLoopPerformBlock(m_cfRunLoop, kCFRunLoopCommonModes, ^{ func(); });
  CFRunLoopWakeUp(m_cfRunLoop);
}

// 往runloop中添加block任务(使用信号量 实现同步)
void RCTMessageThread::runSync(std::function<void()> func) {
  dispatch_semaphore_t sema = dispatch_semaphore_create(0);
  runAsync([func=std::make_shared<std::function<void()>>(std::move(func)), &sema] {
    (*func)();
    dispatch_semaphore_signal(sema);
  });
  dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}

std::unique_ptr<JSExecutor> JSCExecutorFactory::createJSExecutor(
  std::shared_ptr<ExecutorDelegate> delegate,
  std::shared_ptr<MessageQueueThread> jsQueue) {
  
  return folly::make_unique<JSIExecutor>(
    facebook::jsc::makeJSCRuntime(),  // 创建JS Runtime
    delegate,
    [](const std::string &message, unsigned int logLevel) { ... },
    JSIExecutor::defaultTimeoutInvoker,
    std::move(runtimeInstaller_));
}

// NativeModule.h

class NativeModule {
 public:
  virtual ~NativeModule() {}
  // 获取模块信息
  virtual std::string getName() = 0;
  virtual std::vector<MethodDescriptor> getMethods() = 0;
  virtual folly::dynamic getConstants() = 0;
  // 调用原生模块函数
  virtual void invoke(unsigned int reactMethodId, folly::dynamic&& params, int callId) = 0;
  virtual MethodCallResult callSerializableNativeHook(unsigned int reactMethodId, folly::dynamic&& args) = 0;
};
// RCTCxxUtils.mm
// 构建C++原生模块描述对象RCTNativeModule集合
std::vector<std::unique_ptr<NativeModule>> createNativeModules(NSArray<RCTModuleData *> *modules, RCTBridge *bridge, const std::shared_ptr<Instance> &instance)
{
  std::vector<std::unique_ptr<NativeModule>> nativeModules;
  for (RCTModuleData *moduleData in modules) {
    ...
    nativeModules.emplace_back(std::make_unique<RCTNativeModule>(bridge, moduleData));
  }
  return nativeModules;
}
void Instance::initializeBridge(
    std::unique_ptr<InstanceCallback> callback,
    std::shared_ptr<JSExecutorFactory> jsef,
    std::shared_ptr<MessageQueueThread> jsQueue,
    std::shared_ptr<ModuleRegistry> moduleRegistry) {
  callback_ = std::move(callback);
  moduleRegistry_ = std::move(moduleRegistry);
  
  jsQueue->runOnQueueSync([this, &jsef, jsQueue]() mutable {
    // js线程中 同步 初始化NativeToJsBridge
    nativeToJsBridge_ = folly::make_unique<NativeToJsBridge>(
        jsef.get(), moduleRegistry_, jsQueue, callback_);
    
    // 同步信号,初始化 NativeToJsBridge完毕,才允许loadApplicationSync
    std::lock_guard<std::mutex> lock(m_syncMutex);
    m_syncReady = true;
    m_syncCV.notify_all();
  });
}

// 执行JS bundle
void Instance::loadApplication(std::unique_ptr<RAMBundleRegistry> bundleRegistry,
                               std::unique_ptr<const JSBigString> string,
                               std::string sourceURL) {
  nativeToJsBridge_->loadApplication(std::move(bundleRegistry), std::move(string),
                                     std::move(sourceURL));
}

// 调用JS模块函数
void Instance::callJSFunction(std::string &&module, std::string &&method,
                              folly::dynamic &&params) {
  nativeToJsBridge_->callFunction(std::move(module), std::move(method),
                                  std::move(params));
}
// 执行JS回调
void Instance::callJSCallback(uint64_t callbackId, folly::dynamic &&params) {
  nativeToJsBridge_->invokeCallback((double)callbackId, std::move(params));
}

// ModuleRegistry.h

ModuleRegistry(std::vector<std::unique_ptr<NativeModule>> modules, ModuleNotFoundCallback callback = nullptr);

// 生成原生模块配置信息,用于导入JS端
folly::Optional<ModuleConfig> getConfig(const std::string& name);

// 调用用原生模块函数 moduleId:模块索引,methodId:函数索引,params 参数
void callNativeMethod(unsigned int moduleId, unsigned int methodId, folly::dynamic&& params, int callId);
// 调用原生模块同步函数
MethodCallResult callSerializableNativeHook(unsigned int moduleId, unsigned int methodId, folly::dynamic&& args);
  
private:
// C++版本的元原生模块集合 RCTNativeModule
std::vector<std::unique_ptr<NativeModule>> modules_;

// NativeToJsBridge.cpp

// 初始化,构建JsToNativeBridge、JSIExecutor
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)) {}
    
//  执行js bundle
void NativeToJsBridge::loadApplication(
    std::unique_ptr<RAMBundleRegistry> bundleRegistry,
    std::unique_ptr<const JSBigString> startupScript,
    std::string startupScriptSourceURL) {
    ....
}

// 调用JS模块函数 
void NativeToJsBridge::callFunction(
    std::string&& module,
    std::string&& method,
    folly::dynamic&& arguments) { 
    ... 
}
// 执行JS回调
void NativeToJsBridge::invokeCallback(double callbackId, folly::dynamic&& arguments) { ... }

// NativeToJsBridge.cpp

// 调用原生模块函数
void callNativeModules(
      JSExecutor& executor, folly::dynamic&& calls, bool isEndOfBatch) override {
    // 解析函数调用元素,依次执行函数调用(JS call Native批量执行)
    for (auto& call : parseMethodCalls(std::move(calls))) {
      m_registry->callNativeMethod(call.moduleId, call.methodId, std::move(call.arguments), call.callId);
    }
    ...
  }

// 同步调用原生模块函数
  MethodCallResult callSerializableNativeHook(
      JSExecutor& executor, unsigned int moduleId, unsigned int methodId,
      folly::dynamic&& args) override {
    return m_registry->callSerializableNativeHook(moduleId, methodId, std::move(args));
  }

// JSIExecutor.cpp

JSIExecutor::JSIExecutor(
    std::shared_ptr<jsi::Runtime> runtime,
    std::shared_ptr<ExecutorDelegate> delegate,
    Logger logger,
    const JSIScopedTimeoutInvoker& scopedTimeoutInvoker,
    RuntimeInstaller runtimeInstaller)
    : runtime_(runtime),
      delegate_(delegate),
      nativeModules_(delegate ? delegate->getModuleRegistry() : nullptr),
      scopedTimeoutInvoker_(scopedTimeoutInvoker),
      runtimeInstaller_(runtimeInstaller) {
}

// 执行js bundle
void JSIExecutor::loadApplicationScript(
    std::unique_ptr<const JSBigString> script,
    std::string sourceURL) { ... }
    
// 调用JS模块函数 
void JSIExecutor::callFunction(
    const std::string& moduleId,
    const std::string& methodId,
    const folly::dynamic& arguments) { ... }

// 执行JS回调
void JSIExecutor::invokeCallback(
    const double callbackId,
    const folly::dynamic& arguments) { ... }

// 调用原生模块函数
void JSIExecutor::callNativeModules(const Value& queue, bool isEndOfBatch) {  
  // dynamicFromValue 函数调用元素 JS value 转 c++ 动态类型
  delegate_->callNativeModules(
      *this, dynamicFromValue(*runtime_, queue), isEndOfBatch);
}

5.加载js bundle包

加载js bundle包只分析Release模式下本地bundle整包加载流程,对于热更新/RAM拆包加载不做分析。这个过程相对简单,一句话概括:异步加载沙盒中的js bundle包。

// RCTCxxBridge.mm
- (void)start
{
  ...
  // 异步加载 js bundle包
  dispatch_group_enter(prepareBridge);
  __block NSData *sourceCode;
  [self loadSource:^(NSError *error, RCTSource *source) {
    sourceCode = source.data;
    dispatch_group_leave(prepareBridge);
  } onProgress:^(RCTLoadingProgress *progressData) { ... }];
}

- (void)loadSource:(RCTSourceLoadBlock)_onSourceLoad onProgress:(RCTSourceLoadProgressBlock)onProgress
{  
  ...
  RCTSourceLoadBlock onSourceLoad = ^(NSError *error, RCTSource *source) { 
       ...
       _onSourceLoad(error, source);
  };

  [RCTJavaScriptLoader loadBundleAtURL:self.bundleURL onProgress:onProgress onComplete:^(NSError *error, RCTSource *source) {
      onSourceLoad(error, source);
  }];
}
// RCTJavaScriptLoader.mm
+ (void)loadBundleAtURL:(NSURL *)scriptURL onProgress:(RCTSourceLoadProgressBlock)onProgress onComplete:(RCTSourceLoadBlock)onComplete
{
  ...
  if (isCannotLoadSyncError) {
    // 整包,异步加载
    attemptAsynchronousLoadOfBundleAtURL(scriptURL, onProgress, onComplete);
  } else { ... }
}

static void attemptAsynchronousLoadOfBundleAtURL(NSURL *scriptURL, RCTSourceLoadProgressBlock onProgress, RCTSourceLoadBlock onComplete)
{
  scriptURL = sanitizeURL(scriptURL);
  if (scriptURL.fileURL) {
  
 // 整包,异步加载
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSError *error = nil;
NSData *source = [NSData dataWithContentsOfFile:scriptURL.path
                      options:NSDataReadingMappedIfSafe
                        error:&error];
onComplete(error, RCTSourceCreate(scriptURL, source, source.length));
});
return;
}
  ...
}

6.执行js bundle包

上述所有工作完毕,意味着Native&JS通信、执行js bundle包的环境已经构建完毕,最后一个环节:执行执行js bundle包。执行流程图如下,其实就是把js bundle包经过层层传递,最终交给JavaScriptCore去执行。

js bundle执行流程图.png
// RCTCxxBridge.mm
- (void)start
{
   ...
  // 等待”原生模块实例创建完毕、底层Bridge初始化完毕、js bundle包加载完毕“,在JS线程执行js源码
  dispatch_group_notify(prepareBridge, dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
    RCTCxxBridge *strongSelf = weakSelf;
    if (sourceCode && strongSelf.loading) {
      [strongSelf executeSourceCode:sourceCode sync:NO];
    }
  });
}

- (void)executeSourceCode:(NSData *)sourceCode sync:(BOOL)sync
{
  // JS bundle包执行完毕回调
  dispatch_block_t completion = ^{
    // 执行暂存的Native call JS
    [self _flushPendingCalls];
    dispatch_async(dispatch_get_main_queue(), ^{
      // 主线程发送通知
      [[NSNotificationCenter defaultCenter]
       postNotificationName:RCTJavaScriptDidLoadNotification
       object:self->_parentBridge userInfo:@{@"bridge": self}];
      // 开启定时任务,最终用于驱动JS端定时任务
      [self ensureOnJavaScriptThread:^{
        [self->_displayLink addToRunLoop:[NSRunLoop currentRunLoop]];
      }];
    });
  };

  [self enqueueApplicationScript:sourceCode url:self.bundleURL onComplete:completion];
}

- (void)enqueueApplicationScript:(NSData *)script
                             url:(NSURL *)url
                      onComplete:(dispatch_block_t)onComplete
{
  // 底层转化为在JS线程执行JS bundle
  [self executeApplicationScript:script url:url async:YES];
  // JS线程执行回调(由于底层js bundle最终会在JS线程执行,因此可以保证先执行完JS bundle,后执行成功回调)
  if (onComplete) {
    _jsMessageThread->runOnQueue(onComplete);
  }
}

- (void)executeApplicationScript:(NSData *)script
                             url:(NSURL *)url
                           async:(BOOL)async
{
  [self _tryAndHandleError:^{
    NSString *sourceUrlStr = deriveSourceURL(url);
    ...
    // 整包,异步执行
    self->_reactInstance->loadScriptFromString(std::make_unique<NSDataBigString>(script),sourceUrlStr.UTF8String, !async);
  }];
}
// Instance.cpp
void Instance::loadScriptFromString(std::unique_ptr<const JSBigString> string,
                                    std::string sourceURL,
                                    bool loadSynchronously) {
    ...
    loadApplication(nullptr, std::move(string), std::move(sourceURL));
}

void Instance::loadApplication(std::unique_ptr<RAMBundleRegistry> bundleRegistry,
                               std::unique_ptr<const JSBigString> string,
                               std::string sourceURL) {
  nativeToJsBridge_->loadApplication(std::move(bundleRegistry), std::move(string),
                                     std::move(sourceURL));
}
// NativeToJsBridge.cpp
void NativeToJsBridge::loadApplication(
    std::unique_ptr<RAMBundleRegistry> bundleRegistry,
    std::unique_ptr<const JSBigString> startupScript,
    std::string startupScriptSourceURL) {

  // 派发到JS线程执行js bundle
  runOnExecutorQueue( [...] (JSExecutor* executor) mutable {
      ...
      executor->loadApplicationScript(std::move(*startupScript), std::move(startupScriptSourceURL));
  });
}
// JSIExecutor.cpp
void JSIExecutor::loadApplicationScript(
    std::unique_ptr<const JSBigString> script,
    std::string sourceURL) {
  
  // 向JS环境全局对象global注入各种代理,用于向JS端传递原生模块信息、Native&JS互调
  runtime_->global().setProperty( ... );
  ....
  
  // 执行JS脚本
  runtime_->evaluateJavaScript(std::make_unique<BigStringBuffer>(std::move(script)), sourceURL);
  
  // 执行JS异步任务,JS call Navite
  flush();
}

至此ReactNative启动流程已经完毕,开始运行js bundle代码,执行前面RCTRootView调用JS模块AppRegistry runApplication,运行组件,开始页面渲染。。。。

四、启动流程线程管理

RCTCxxBridge.mm
- (void)start
{
  dispatch_group_t prepareBridge = dispatch_group_create();

  // 3.加载自动注册的原生模块
  (void)[self _initializeModules:RCTGetModuleClasses() withDispatchGroup:prepareBridge lazilyDiscovered:NO];
 
  // 4.js线程中初始化底层底层Bridge
  dispatch_group_enter(prepareBridge);
  [self ensureOnJavaScriptThread:^{
    [weakSelf _initializeBridge:executorFactory];
    dispatch_group_leave(prepareBridge);
  }];

  // 5.加载 js bundle包(整包,异步加载)
  dispatch_group_enter(prepareBridge);
  __block NSData *sourceCode;
  [self loadSource:^(NSError *error, RCTSource *source) {
    sourceCode = source.data;
    dispatch_group_leave(prepareBridge);
  } onProgress:^(RCTLoadingProgress *progressData) { ... }];

  // 6.执行js bundle 源码
  dispatch_group_notify(prepareBridge, dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
    RCTCxxBridge *strongSelf = weakSelf;
    if (sourceCode && strongSelf.loading) {
      [strongSelf executeSourceCode:sourceCode sync:NO];
    }
  });
}

- (void)_prepareModulesWithDispatchGroup:(dispatch_group_t)dispatchGroup
{
  for (RCTModuleData *moduleData in _moduleDataByID) {
    if (moduleData.requiresMainQueueSetup) {
      dispatch_block_t block = ^{
          // 创建模块实例
          (void)[moduleData instance];
          [moduleData gatherConstants];
      };

      if (initializeImmediately && RCTIsMainQueue()) {
        block();
      } else {
        //  异步派发模块实例创建任务到主队列
        if (dispatchGroup) {
          dispatch_group_async(dispatchGroup, dispatch_get_main_queue(), block);
        }
      }
      _modulesInitializedOnMainQueue++;
    }
  }
}

Reference

上一篇下一篇

猜你喜欢

热点阅读