React Native是怎么在Android上跑起来的

本文剖析了React Native如何在Android平台上运行,从启动流程、通信机制、事件驱动到渲染原理和脚本执行。启动始于Activity,通信机制依赖于Java端与JS端的映射表,渲染原理涉及组件注册表和React Native Bridge。事件驱动利用Android的Choreographer进行同步。
摘要由CSDN通过智能技术生成

(源码版本:0.34,新版本(0.48)基本流程是不变的,建议跟着源码看看,哪个版本的倒影响不大)
这篇简单刨析一下React Native是怎么在Android上跑起来的,会从下面几个方面说说。

  • 启动流程
  • 通信机制
  • 事件驱动
  • 渲染原理
  • 脚本执行

启动流程

React NativeAndroid上启动是从ReactRootView.startReactApplication触发的,而ReactRootView是继承FrameLayout的,所以React NativeAndroid的操作都是在这个View中进行的。

startReactApplication(ReactInstanceManager reactInstanceManager, String moduleName, @Nullable Bundle launchOptions)

这个方法参数第一个ReactInstanceManager,实现是XReactInstanceManagerImpl,可以理解在应用层对RN的配置都是对这个类操作实现的。moduleName是要启动的RNComponentname,是在jsAppRegistry.registerComponent('xxx', () => App);定义的。最后的launchOptions是传过去的参数,可以在jsComponentprops中获取。

下一步到了mReactInstanceManager.createReactContextInBackground();是在后台线程中创建RNReactContext上下文对象,然后到

//JavaScriptExecutor 默认就是jsc,如果的debug在chrome上时候,就是v8。
//JSBundleLoader 有AssetLoader FileLoader CachedBundleFromNetworkLoader RemoteDebuggerBundleLoader 从不同的地方加载bundle
 private void recreateReactContextInBackground(
      JavaScriptExecutor.Factory jsExecutorFactory,
      JSBundleLoader jsBundleLoader) {
    UiThreadUtil.assertOnUiThread();

    ReactContextInitParams initParams =
        new ReactContextInitParams(jsExecutorFactory, jsBundleLoader);
    if (mReactContextInitAsyncTask == null) {
      // No background task to create react context is currently running, create and execute one.
      mReactContextInitAsyncTask = new ReactContextInitAsyncTask();
      mReactContextInitAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, initParams);
    } else {
      // Background task is currently running, queue up most recent init params to recreate context
      // once task completes.
      mPendingReactContextInitParams = initParams;
    }
  }

主要的创建工作就转移到了ReactContextInitAsyncTask这个AsyncTask里面,

 @Override
    protected Result<ReactApplicationContext> doInBackground(ReactContextInitParams... params) {
      ....
       return Result.of(createReactContext(jsExecutor, params[0].getJsBundleLoader()));
      ....
    }

  private ReactApplicationContext createReactContext(
      JavaScriptExecutor jsExecutor,
      JSBundleLoader jsBundleLoader) {
    ...
     NativeModuleRegistry.Builder nativeRegistryBuilder = new NativeModuleRegistry.Builder();//NativeModule的注册表
    JavaScriptModuleRegistry.Builder jsModulesBuilder = new JavaScriptModuleRegistry.Builder();//jsModules的注册表
    ...打包定义的各种modules到上面的注册表...

        //创建关键的CatalystInstanceImpl
        CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder()
        ...
        catalystInstance = catalystInstanceBuilder.build();
    ....
    //扔到js线程中加载js脚本
    catalystInstance.getReactQueueConfiguration().getJSQueueThread().callOnQueue(
        new Callable<Void>() {
          @Override
          public Void call() throws Exception {
            //让reactContext持有catalystInstance
            reactContext.initializeWithInstance(catalystInstance);
            ...
            catalystInstance.runJSBundle();
            return null;
          }
        }).get();
    }

CatalystInstanceImpl的构造函数中有

...
//native C++方法,用来初始化JNI相关状态然后返回mHybridData。具体在 OnLoad.cpp 的 JSCJavaScriptExecutorHolder 类中
mHybridData = initHybrid();
...
//初始化线程环境,包括和主线程绑定,JS线程,Native线程创建。
mReactQueueConfiguration = ReactQueueConfigurationImpl.create(
        ReactQueueConfigurationSpec,
        new NativeExceptionHandler());
...
initializeBridge(
      new BridgeCallback(this),//CatalystInstanceImpl内部类,用于native对java的一些回调
      jsExecutor,//jsc
      mReactQueueConfiguration.getJSQueueThread(),//js线程队列
      mReactQueueConfiguration.getNativeModulesQueueThread(),//native线程队列
      mJavaRegistry.getModuleRegistryHolder(this));//nativemodules注册表
    mMainExecutorToken = getMainExecutorToken();//貌似是用于切换jsExecutor的标记,后面版本删掉了。

然后就进入到了cpp层的CatalystInstanceImpl.cppinitializeBridge方法

void CatalystInstanceImpl::initializeBridge(
    jni::alias_ref<ReactCallback::javaobject> callback,
    // This executor is actually a factory holder.
    JavaScriptExecutorHolder* jseh,
    jni::alias_ref<JavaMessageQueueThread::javaobject> jsQueue,
    jni::alias_ref<JavaMessageQueueThread::javaobject> moduleQueue,
    ModuleRegistryHolder* mrh) {

  instance_->initializeBridge(folly::make_unique<JInstanceCallback>(callback),
                              jseh->getExecutorFactory(),
                              folly::make_unique<JMessageQueueThread>(jsQueue),
                              folly::make_unique<JMessageQueueThread>(moduleQueue),
                              mrh->getModuleRegistry());
}

然后有委托给了Instance.cppinitializeBridge方法

void Instance::initializeBridge(
    std::unique_ptr<InstanceCallback> callback,
    std::shared_ptr<JSExecutorFactory> jsef,
    std::shared_ptr<MessageQueueThread> jsQueue,
    std::unique_ptr<MessageQueueThread> nativeQueue,
    std::shared_ptr<ModuleRegistry> moduleRegistry) {
  callback_ = std::move(callback);

  //在js线程中包装nativeQueue和创建nativeToJsBridge_,后者在双向bridge起作用,不要仅仅看名字,内部还有一个JsToNativeBridge
  jsQueue->runOnQueueSync(
    [this, &js
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值