React Native 0.55.4 Android 源碼分析(Java層源碼解析)

一诫尽、React Native常量概念

1、ReactRootView是RN界面的最頂層的View炬守,主要負(fù)責(zé)進(jìn)行監(jiān)聽分發(fā)事件,渲染元素等工作剂跟。它可以通過監(jiān)聽View的尺寸從而使UIManager可以對(duì)其子元素進(jìn)行重新布局减途。
2、ReactInstanceManager主要被用于管理CatalystInstance實(shí)例對(duì)象曹洽。通過ReactPackage鳍置,它向開發(fā)人員提供了配置和使用CatalystInstance實(shí)例對(duì)象的方法,并對(duì)該CatalystInstance實(shí)例的生命周期進(jìn)行追蹤送淆。ReactInstanceManager實(shí)例對(duì)象的生命周期與ReactRootView所在的Activity保持一致税产。
3、ReactNativeHost一個(gè)普通的抽象類偷崩,提供一些相關(guān)的方法辟拷,主要提供ReactInstanceManager的創(chuàng)建
4、NativeModuleRegistry一組Java API阐斜,以暴露給特定的JavaScript實(shí)例衫冻。暴露原生方法給JS
5、CatalystInstance異步JSC橋上的更高級(jí)API谒出。 提供了一個(gè)允許調(diào)用JavaScript方法的環(huán)境隅俘,并允許一組Java API也可以從JavaScript調(diào)用。
6笤喳、HybridData一個(gè)持有C++層對(duì)象實(shí)例指針的Java層實(shí)例为居,負(fù)責(zé)Java層和C++層之間的數(shù)據(jù)傳輸

二、React Native啟動(dòng)流程分析

ReactNative啟動(dòng)流程.png

1杀狡、Application初始化ReactNativeHost

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
            return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
            return Arrays.<ReactPackage>asList(
                    new MainReactPackage(),
                    new RNFSPackage(),
                    new LottiePackage(),
                    new AutoHeightWebViewPackage(),
                    new MReactPackage(),
                    new LinearGradientPackage(),
                    new CodePush(BuildConfig.CODEPUSH_KEY, SysApplication.this, BuildConfig.DEBUG),
                    new SvgPackage(),
                    new RNViewShotPackage(),
                    new RNSentryPackage()
            );
        }

        @Override
        protected String getJSBundleFile() {
            return CodePush.getJSBundleFile();
        }
    };

    @Override
    public ReactNativeHost getReactNativeHost() {
        return mReactNativeHost;
    }

2蒙畴、ReactInstanceManager的初始化

mReactInstanceManager = ((ReactApplication) GlobalServiceManager.getService(IAppService.class).getAppContext())
                .getReactNativeHost()
                .getReactInstanceManager();

首先來看getReactInstanceManager()調(diào)用了createReactInstanceManager()createReactInstanceManager()中代碼如下

  /**
   * Get the current {@link ReactInstanceManager} instance, or create one.
   */
  public ReactInstanceManager getReactInstanceManager() {
    if (mReactInstanceManager == null) {
      ReactMarker.logMarker(ReactMarkerConstants.GET_REACT_INSTANCE_MANAGER_START);
      mReactInstanceManager = createReactInstanceManager();
      ReactMarker.logMarker(ReactMarkerConstants.GET_REACT_INSTANCE_MANAGER_END);
    }
    return mReactInstanceManager;
  }


  protected ReactInstanceManager createReactInstanceManager() {
    ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_START);
    ReactInstanceManagerBuilder builder = ReactInstanceManager.builder()
      .setApplication(mApplication)
      .setJSMainModulePath(getJSMainModuleName())
      .setUseDeveloperSupport(getUseDeveloperSupport())
      .setRedBoxHandler(getRedBoxHandler())
      .setJavaScriptExecutorFactory(getJavaScriptExecutorFactory())
      .setUIImplementationProvider(getUIImplementationProvider())
      .setJSIModulesProvider(getJSIModulesProvider())
      .setInitialLifecycleState(LifecycleState.BEFORE_CREATE);

    for (ReactPackage reactPackage : getPackages()) {
      builder.addPackage(reactPackage);
    }

    String jsBundleFile = getJSBundleFile();
    if (jsBundleFile != null) {
      builder.setJSBundleFile(jsBundleFile);
    } else {
      builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName()));
    }
    ReactInstanceManager reactInstanceManager = builder.build();
    ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_END);
    return reactInstanceManager;
  }

可以看到創(chuàng)建ReactInstanceManager的步驟是這樣的

  • 創(chuàng)建ReactInstanceManagerBuilder對(duì)象
  • 把在ReactNativeHost中注冊(cè)的ReactPackage全部添加到ReactInstanceManagerBuilder實(shí)例化對(duì)象中
  • 如果getJSBundleFile()有在ReactNativeHost注冊(cè)聲明則加載相應(yīng)文件捣卤,沒有則去加載默認(rèn)生成的JSBundleFile
  • 調(diào)用ReactInstanceManagerBuilder實(shí)例對(duì)象的build()構(gòu)造實(shí)例
    ReactInstanceManagerBuilderbuild()方法如下
/**
   * Instantiates a new {@link ReactInstanceManager}.
   * Before calling {@code build}, the following must be called:
   * <ul>
   * <li> {@link #setApplication}
   * <li> {@link #setCurrentActivity} if the activity has already resumed
   * <li> {@link #setDefaultHardwareBackBtnHandler} if the activity has already resumed
   * <li> {@link #setJSBundleFile} or {@link #setJSMainModulePath}
   * </ul>
   */
  public ReactInstanceManager build() {
    Assertions.assertNotNull(
      mApplication,
      "Application property has not been set with this builder");

    Assertions.assertCondition(
      mUseDeveloperSupport || mJSBundleAssetUrl != null || mJSBundleLoader != null,
      "JS Bundle File or Asset URL has to be provided when dev support is disabled");

    Assertions.assertCondition(
      mJSMainModulePath != null || mJSBundleAssetUrl != null || mJSBundleLoader != null,
      "Either MainModulePath or JS Bundle File needs to be provided");

    if (mUIImplementationProvider == null) {
      // create default UIImplementationProvider if the provided one is null.
      mUIImplementationProvider = new UIImplementationProvider();
    }

    // We use the name of the device and the app for debugging & metrics
    String appName = mApplication.getPackageName();
    String deviceName = getFriendlyDeviceName();

    return new ReactInstanceManager(
        mApplication,
        mCurrentActivity,
        mDefaultHardwareBackBtnHandler,
        mJavaScriptExecutorFactory == null
            ? new JSCJavaScriptExecutorFactory(appName, deviceName)
            : mJavaScriptExecutorFactory,
        (mJSBundleLoader == null && mJSBundleAssetUrl != null)
            ? JSBundleLoader.createAssetLoader(
                mApplication, mJSBundleAssetUrl, false /*Asynchronous*/)
            : mJSBundleLoader,
        mJSMainModulePath,
        mPackages,
        mUseDeveloperSupport,
        mBridgeIdleDebugListener,
        Assertions.assertNotNull(mInitialLifecycleState, "Initial lifecycle state was not set"),
        mUIImplementationProvider,
        mNativeModuleCallExceptionHandler,
        mRedBoxHandler,
        mLazyNativeModulesEnabled,
        mLazyViewManagersEnabled,
        mDelayViewManagerClassLoadsEnabled,
        mDevBundleDownloadListener,
        mMinNumShakes,
        mMinTimeLeftInFrameForNonBatchedOperationMs,
      mJSIModulesProvider);
  }

這里需要注意的2個(gè)地方的初始化

   mJavaScriptExecutorFactory == null
            ? new JSCJavaScriptExecutorFactory(appName, deviceName)
            : mJavaScriptExecutorFactory,
   (mJSBundleLoader == null && mJSBundleAssetUrl != null)
          ? JSBundleLoader.createAssetLoader(
            mApplication, mJSBundleAssetUrl, false /*Asynchronous*/)
            : mJSBundleLoader,

其中JSCJavaScriptExecutorFactoryJavaScriptExecutorFactory的實(shí)現(xiàn)忍抽,負(fù)責(zé)創(chuàng)建相應(yīng)的JavaScriptExecutor,JSBundleLoader.createAssetLoader()則創(chuàng)建相應(yīng)的JSBundleLoader

  /**
   * This loader is recommended one for release version of your app. In that case local JS executor
   * should be used. JS bundle will be read from assets in native code to save on passing large
   * strings from java to native memory.
   */
  public static JSBundleLoader createAssetLoader(
      final Context context,
      final String assetUrl,
      final boolean loadSynchronously) {
    return new JSBundleLoader() {
      @Override
      public String loadScript(CatalystInstanceImpl instance) {
        instance.loadScriptFromAssets(context.getAssets(), assetUrl, loadSynchronously);
        return assetUrl;
      }
    };
  }

3、ReactRootViewJS應(yīng)用程序的關(guān)聯(lián)

  mReactRootView.startReactApplication(
      mReactInstanceManager,
      getMainComponentName(),
      appProperties
  );

ReactRootView通過startReactApplication方法關(guān)聯(lián)JS相應(yīng)模塊董朝,進(jìn)入startReactApplication源碼

  /**
   * Schedule rendering of the react component rendered by the JS application from the given JS
   * module (@{param moduleName}) using provided {@param reactInstanceManager} to attach to the
   * JS context of that manager. Extra parameter {@param launchOptions} can be used to pass initial
   * properties for the react component.
   */
  public void startReactApplication(
      ReactInstanceManager reactInstanceManager,
      String moduleName,
      @Nullable Bundle initialProperties) {
    Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "startReactApplication");
    try {
      UiThreadUtil.assertOnUiThread();

      // TODO(6788889): Use POJO instead of bundle here, apparently we can't just use WritableMap
      // here as it may be deallocated in native after passing via JNI bridge, but we want to reuse
      // it in the case of re-creating the catalyst instance
      Assertions.assertCondition(
        mReactInstanceManager == null,
        "This root view has already been attached to a catalyst instance manager");

      mReactInstanceManager = reactInstanceManager;
      mJSModuleName = moduleName;
      mAppProperties = initialProperties;

      if (!mReactInstanceManager.hasStartedCreatingInitialContext()) {
        mReactInstanceManager.createReactContextInBackground();
      }

      attachToReactInstanceManager();

    } finally {
      Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
    }
  }

首先追蹤createReactContextInBackground()方法,忽略Debug環(huán)境的一些初始化代碼鸠项,最后追蹤到下面這個(gè)方法

  @ThreadConfined(UI)
  private void recreateReactContextInBackgroundFromBundleLoader() {
    Log.d(
      ReactConstants.TAG,
      "ReactInstanceManager.recreateReactContextInBackgroundFromBundleLoader()");
    PrinterHolder.getPrinter()
        .logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: load from BundleLoader");
    recreateReactContextInBackground(mJavaScriptExecutorFactory, mBundleLoader);
  }

這里的mJavaScriptExecutorFactorymBundleLoader則是上面初始化ReactInstanceManager時(shí)已經(jīng)構(gòu)建的,繼續(xù)追蹤recreateReactContextInBackground(),部分代碼已省略

  @ThreadConfined(UI)
  private void runCreateReactContextOnNewThread(final ReactContextInitParams initParams) {
    ..................
    mCreateReactContextThread =
        new Thread(
            new Runnable() {
              @Override
              public void run() {
                 ................
                try {
                  Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
                  final ReactApplicationContext reactApplicationContext =
                      createReactContext(
                          initParams.getJsExecutorFactory().create(),
                          initParams.getJsBundleLoader());
                  .................
                  Runnable setupReactContextRunnable =
                      new Runnable() {
                        @Override
                        public void run() {
                          try {
                            setupReactContext(reactApplicationContext);
                          } catch (Exception e) {
                            mDevSupportManager.handleException(e);
                          }
                        }
                      };

                  reactApplicationContext.runOnNativeModulesQueueThread(setupReactContextRunnable);
                  UiThreadUtil.runOnUiThread(maybeRecreateReactContextRunnable);
                } catch (Exception e) {
                  mDevSupportManager.handleException(e);
                }
              }
            });
    ReactMarker.logMarker(REACT_CONTEXT_THREAD_START);
    mCreateReactContextThread.start();
  }

進(jìn)入createReactContext()里追蹤

  /**
   * @return instance of {@link ReactContext} configured a {@link CatalystInstance} set
   */
  private ReactApplicationContext createReactContext(
      JavaScriptExecutor jsExecutor,
      JSBundleLoader jsBundleLoader) {
    Log.d(ReactConstants.TAG, "ReactInstanceManager.createReactContext()");
    ReactMarker.logMarker(CREATE_REACT_CONTEXT_START);
    final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);

    if (mUseDeveloperSupport) {
      reactContext.setNativeModuleCallExceptionHandler(mDevSupportManager);
    }

    NativeModuleRegistry nativeModuleRegistry = processPackages(reactContext, mPackages, false);

    NativeModuleCallExceptionHandler exceptionHandler = mNativeModuleCallExceptionHandler != null
      ? mNativeModuleCallExceptionHandler
      : mDevSupportManager;
    CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder()
      .setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
      .setJSExecutor(jsExecutor)
      .setRegistry(nativeModuleRegistry)
      .setJSBundleLoader(jsBundleLoader)
      .setNativeModuleCallExceptionHandler(exceptionHandler);

    ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_START);
    // CREATE_CATALYST_INSTANCE_END is in JSCExecutor.cpp
    Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "createCatalystInstance");
    final CatalystInstance catalystInstance;
    try {
      catalystInstance = catalystInstanceBuilder.build();
    } finally {
      Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
      ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_END);
    }
    if (mJSIModulesProvider != null) {
      catalystInstance.addJSIModules(mJSIModulesProvider
        .getJSIModules(reactContext, catalystInstance.getJavaScriptContextHolder()));
    }

    if (mBridgeIdleDebugListener != null) {
      catalystInstance.addBridgeIdleDebugListener(mBridgeIdleDebugListener);
    }
    if (Systrace.isTracing(TRACE_TAG_REACT_APPS | TRACE_TAG_REACT_JS_VM_CALLS)) {
      catalystInstance.setGlobalVariable("__RCTProfileIsProfiling", "true");
    }
    ReactMarker.logMarker(ReactMarkerConstants.PRE_RUN_JS_BUNDLE_START);
    catalystInstance.runJSBundle();
    reactContext.initializeWithInstance(catalystInstance);

    return reactContext;
  }

這個(gè)方法里主要做了這幾件事情

  • 創(chuàng)建ReactApplicationContext實(shí)例
  • 創(chuàng)建NativeModuleRegistry
  • 創(chuàng)建CatalystInstance
  • 執(zhí)行JS端代碼初始化
  • 初始化ReactApplicationContext實(shí)例的mCatalystInstance對(duì)象

(1)NativeModuleRegistry的創(chuàng)建主要看一下NativeModuleRegistryBuilder的創(chuàng)建代碼

  public void processPackage(ReactPackage reactPackage) {
    if (mLazyNativeModulesEnabled) {
      if (!(reactPackage instanceof LazyReactPackage)) {
        throw new IllegalStateException("Lazy native modules requires all ReactPackage to " +
          "inherit from LazyReactPackage");
      }

      LazyReactPackage lazyReactPackage = (LazyReactPackage) reactPackage;
      List<ModuleSpec> moduleSpecs = lazyReactPackage.getNativeModules(mReactApplicationContext);
      Map<Class, ReactModuleInfo> reactModuleInfoMap = lazyReactPackage.getReactModuleInfoProvider()
        .getReactModuleInfos();

      for (ModuleSpec moduleSpec : moduleSpecs) {
        Class<? extends NativeModule> type = moduleSpec.getType();
        ReactModuleInfo reactModuleInfo = reactModuleInfoMap.get(type);
        ModuleHolder moduleHolder;
        if (reactModuleInfo == null) {
          if (BaseJavaModule.class.isAssignableFrom(type)) {
            throw new IllegalStateException("Native Java module " + type.getSimpleName() +
              " should be annotated with @ReactModule and added to a @ReactModuleList.");
          }
          NativeModule module;
          ReactMarker.logMarker(
            ReactMarkerConstants.CREATE_MODULE_START,
            moduleSpec.getType().getName());
          try {
            module = moduleSpec.getProvider().get();
          } finally {
            ReactMarker.logMarker(ReactMarkerConstants.CREATE_MODULE_END);
          }
          moduleHolder = new ModuleHolder(module);
        } else {
          moduleHolder = new ModuleHolder(reactModuleInfo, moduleSpec.getProvider());
        }

        String name = moduleHolder.getName();
        if (namesToType.containsKey(name)) {
          Class<? extends NativeModule> existingNativeModule = namesToType.get(name);
          if (!moduleHolder.getCanOverrideExistingModule()) {
            throw new IllegalStateException("Native module " + type.getSimpleName() +
              " tried to override " + existingNativeModule.getSimpleName() + " for module name " +
              name + ". If this was your intention, set canOverrideExistingModule=true");
          }

          mModules.remove(existingNativeModule);
        }

        namesToType.put(name, type);
        mModules.put(type, moduleHolder);
      }
    } else {
      FLog.d(
        ReactConstants.TAG,
        reactPackage.getClass().getSimpleName() +
          " is not a LazyReactPackage, falling back to old version.");
      List<NativeModule> nativeModules;
      if (reactPackage instanceof ReactInstancePackage) {
        ReactInstancePackage reactInstancePackage = (ReactInstancePackage) reactPackage;
        nativeModules = reactInstancePackage.createNativeModules(
            mReactApplicationContext,
            mReactInstanceManager);
      } else {
        nativeModules = reactPackage.createNativeModules(mReactApplicationContext);
      }
      for (NativeModule nativeModule : nativeModules) {
        addNativeModule(nativeModule);
      }
    }
  }

分為2種加載模式子姜,懶加載和正常加載祟绊。最后都是把在ReactNativeHost中注冊(cè)的ReactPackage放入一個(gè)Map映射內(nèi)

  public void addNativeModule(NativeModule nativeModule) {
    String name = nativeModule.getName();
    Class<? extends NativeModule> type = nativeModule.getClass();
    if (namesToType.containsKey(name)) {
      Class<? extends NativeModule> existingModule = namesToType.get(name);
      if (!nativeModule.canOverrideExistingModule()) {
        throw new IllegalStateException("Native module " + type.getSimpleName() +
          " tried to override " + existingModule.getSimpleName() + " for module name " +
          name + ". If this was your intention, set canOverrideExistingModule=true");
      }

      mModules.remove(existingModule);
    }

    namesToType.put(name, type);
    ModuleHolder moduleHolder = new ModuleHolder(nativeModule);
    mModules.put(type, moduleHolder);
  }

然后調(diào)用build()方法構(gòu)建NativeModuleRegistry

  public NativeModuleRegistry build() {
    ArrayList<ModuleHolder> batchCompleteListenerModules = new ArrayList<>();
    for (Map.Entry<Class<? extends NativeModule>, ModuleHolder> entry : mModules.entrySet()) {
      if (OnBatchCompleteListener.class.isAssignableFrom(entry.getKey())) {
        batchCompleteListenerModules.add(entry.getValue());
      }
    }

    return new NativeModuleRegistry(
      mReactApplicationContext,
      mModules,
      batchCompleteListenerModules);
  }

(2)CatalystInstance實(shí)例的創(chuàng)建

    CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder()
      .setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
      .setJSExecutor(jsExecutor)
      .setRegistry(nativeModuleRegistry)
      .setJSBundleLoader(jsBundleLoader)
      .setNativeModuleCallExceptionHandler(exceptionHandler);

    ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_START);
    // CREATE_CATALYST_INSTANCE_END is in JSCExecutor.cpp
    Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "createCatalystInstance");
    final CatalystInstance catalystInstance;
    try {
      catalystInstance = catalystInstanceBuilder.build();
    } finally {
      Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
      ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_END);
    }

追蹤CatalystInstanceImpl實(shí)例的初始化過程楼入,這邊則是重點(diǎn),實(shí)現(xiàn)了Java端和C++的關(guān)聯(lián)

  private CatalystInstanceImpl(
      final ReactQueueConfigurationSpec reactQueueConfigurationSpec,
      final JavaScriptExecutor jsExecutor,
      final NativeModuleRegistry nativeModuleRegistry,
      final JSBundleLoader jsBundleLoader,
      NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler) {
    Log.d(ReactConstants.TAG, "Initializing React Xplat Bridge.");
    mHybridData = initHybrid();

    mReactQueueConfiguration = ReactQueueConfigurationImpl.create(
        reactQueueConfigurationSpec,
        new NativeExceptionHandler());
    mBridgeIdleListeners = new CopyOnWriteArrayList<>();
    mNativeModuleRegistry = nativeModuleRegistry;
    mJSModuleRegistry = new JavaScriptModuleRegistry();
    mJSBundleLoader = jsBundleLoader;
    mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler;
    mNativeModulesQueueThread = mReactQueueConfiguration.getNativeModulesQueueThread();
    mTraceListener = new JSProfilerTraceListener(this);

    Log.d(ReactConstants.TAG, "Initializing React Xplat Bridge before initializeBridge");
    initializeBridge(
      new BridgeCallback(this),
      jsExecutor,
      mReactQueueConfiguration.getJSQueueThread(),
      mNativeModulesQueueThread,
      mNativeModuleRegistry.getJavaModules(this),
      mNativeModuleRegistry.getCxxModules());
    Log.d(ReactConstants.TAG, "Initializing React Xplat Bridge after initializeBridge");

    mJavaScriptContextHolder = new JavaScriptContextHolder(getJavaScriptContext());
  }

主要就是下面的2個(gè)方法

  private native static HybridData initHybrid();

初始化HybridData牧抽,使得Java對(duì)象持有C++對(duì)象的指針

  private native void initializeBridge(
      ReactCallback callback,
      JavaScriptExecutor jsExecutor,
      MessageQueueThread jsQueue,
      MessageQueueThread moduleQueue,
      Collection<JavaModuleWrapper> javaModules,
      Collection<ModuleHolder> cxxModules);

初始化Java端和C++的橋

如果追蹤C(jī)++層代碼嘉熊,可以發(fā)現(xiàn)以下代碼,具體的初始化過程這里不再深入

void CatalystInstanceImpl::registerNatives() {
  registerHybrid({
    makeNativeMethod("initHybrid", CatalystInstanceImpl::initHybrid),
    makeNativeMethod("initializeBridge", CatalystInstanceImpl::initializeBridge),
    makeNativeMethod("jniExtendNativeModules", CatalystInstanceImpl::extendNativeModules),
    makeNativeMethod("jniSetSourceURL", CatalystInstanceImpl::jniSetSourceURL),
    makeNativeMethod("jniRegisterSegment", CatalystInstanceImpl::jniRegisterSegment),
    makeNativeMethod("jniLoadScriptFromAssets", CatalystInstanceImpl::jniLoadScriptFromAssets),
    makeNativeMethod("jniLoadScriptFromFile", CatalystInstanceImpl::jniLoadScriptFromFile),
    makeNativeMethod("jniLoadScriptFromDeltaBundle", CatalystInstanceImpl::jniLoadScriptFromDeltaBundle),
    makeNativeMethod("jniCallJSFunction", CatalystInstanceImpl::jniCallJSFunction),
    makeNativeMethod("jniCallJSCallback", CatalystInstanceImpl::jniCallJSCallback),
    makeNativeMethod("setGlobalVariable", CatalystInstanceImpl::setGlobalVariable),
    makeNativeMethod("getJavaScriptContext", CatalystInstanceImpl::getJavaScriptContext),
    makeNativeMethod("jniHandleMemoryPressure", CatalystInstanceImpl::handleMemoryPressure),
  });

  JNativeRunnable::registerNatives();
}

映射initHybridCatalystInstanceImpl.cpp類中的initHybrid方法扬舒,映射initializeBridgeCatalystInstanceImpl.cppinitializeBridge方法阐肤,如果有興趣的同學(xué)可以下載React Native源碼才開ReactAndroid NDK部分。
關(guān)于通訊數(shù)據(jù)模型可以參考這篇文章讲坎,本文不再贅述孕惜。React-Native系列Android——通信數(shù)據(jù)模型分析

(3)執(zhí)行JS端的初始化

JS端代碼初始化調(diào)用CatalystInstance實(shí)例的runJSBundle()方法

  @Override
  public void runJSBundle() {
    Log.d(ReactConstants.TAG, "CatalystInstanceImpl.runJSBundle()");
    Assertions.assertCondition(!mJSBundleHasLoaded, "JS bundle was already loaded!");
    // incrementPendingJSCalls();
    mJSBundleLoader.loadScript(CatalystInstanceImpl.this);

    synchronized (mJSCallsPendingInitLock) {

      // Loading the bundle is queued on the JS thread, but may not have
      // run yet.  It's safe to set this here, though, since any work it
      // gates will be queued on the JS thread behind the load.
      mAcceptCalls = true;

      for (PendingJSCall function : mJSCallsPendingInit) {
        function.call(this);
      }
      mJSCallsPendingInit.clear();
      mJSBundleHasLoaded = true;
    }

    // This is registered after JS starts since it makes a JS call
    Systrace.registerListener(mTraceListener);
  }

可以看到這邊調(diào)用了mJSBundleLoaderloadScript方法,而這個(gè)方法在初始化ReactInstanceManager調(diào)用了JSBundleLoader.createAssetLoader進(jìn)行了實(shí)現(xiàn)。

 /**
   * This loader is recommended one for release version of your app. In that case local JS executor
   * should be used. JS bundle will be read from assets in native code to save on passing large
   * strings from java to native memory.
   */
  public static JSBundleLoader createAssetLoader(
      final Context context,
      final String assetUrl,
      final boolean loadSynchronously) {
    return new JSBundleLoader() {
      @Override
      public String loadScript(CatalystInstanceImpl instance) {
        instance.loadScriptFromAssets(context.getAssets(), assetUrl, loadSynchronously);
        return assetUrl;
      }
    };
  }

繼續(xù)追蹤可以發(fā)現(xiàn)這邊調(diào)用了C++層的代碼初始化

  private native void jniLoadScriptFromAssets(AssetManager assetManager, String assetURL, boolean loadSynchronously);

(4)初始化ReactApplicationContext實(shí)例的mCatalystInstance對(duì)象

  /**
   * Set and initialize CatalystInstance for this Context. This should be called exactly once.
   */
  public void initializeWithInstance(CatalystInstance catalystInstance) {
    if (catalystInstance == null) {
      throw new IllegalArgumentException("CatalystInstance cannot be null.");
    }
    if (mCatalystInstance != null) {
      throw new IllegalStateException("ReactContext has been already initialized");
    }

    mCatalystInstance = catalystInstance;

    ReactQueueConfiguration queueConfig = catalystInstance.getReactQueueConfiguration();
    mUiMessageQueueThread = queueConfig.getUIQueueThread();
    mNativeModulesMessageQueueThread = queueConfig.getNativeModulesQueueThread();
    mJSMessageQueueThread = queueConfig.getJSQueueThread();
  }

到這里只是分析了createReactContext()方法里所做的事情晨炕,createReactContext()最后返回了ReactApplicationContext的實(shí)例化對(duì)象衫画。而這個(gè)實(shí)例化對(duì)象被setupReactContext()所調(diào)用,進(jìn)一步追蹤源碼

    private void setupReactContext(final ReactApplicationContext reactContext) {
    Log.d(ReactConstants.TAG, "ReactInstanceManager.setupReactContext()");
    ReactMarker.logMarker(PRE_SETUP_REACT_CONTEXT_END);
    ReactMarker.logMarker(SETUP_REACT_CONTEXT_START);
    Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "setupReactContext");
    synchronized (mReactContextLock) {
      mCurrentReactContext = Assertions.assertNotNull(reactContext);
    }
    CatalystInstance catalystInstance =
      Assertions.assertNotNull(reactContext.getCatalystInstance());

    catalystInstance.initialize();
    mDevSupportManager.onNewReactContextCreated(reactContext);
    mMemoryPressureRouter.addMemoryPressureListener(catalystInstance);
    moveReactContextToCurrentLifecycleState();

    ReactMarker.logMarker(ATTACH_MEASURED_ROOT_VIEWS_START);
    synchronized (mAttachedRootViews) {
      for (ReactRootView rootView : mAttachedRootViews) {
        attachRootViewToInstance(rootView, catalystInstance);
      }
    }
    ReactMarker.logMarker(ATTACH_MEASURED_ROOT_VIEWS_END);

    ReactInstanceEventListener[] listeners =
      new ReactInstanceEventListener[mReactInstanceEventListeners.size()];
    final ReactInstanceEventListener[] finalListeners =
        mReactInstanceEventListeners.toArray(listeners);

    UiThreadUtil.runOnUiThread(
        new Runnable() {
          @Override
          public void run() {
            for (ReactInstanceEventListener listener : finalListeners) {
              listener.onReactContextInitialized(reactContext);
            }
          }
        });
    Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
    ReactMarker.logMarker(SETUP_REACT_CONTEXT_END);
    reactContext.runOnJSQueueThread(
        new Runnable() {
          @Override
          public void run() {
            Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
          }
        });
    reactContext.runOnNativeModulesQueueThread(
        new Runnable() {
          @Override
          public void run() {
            Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
          }
        });
  } 

這個(gè)方法主要做了這些事情

  • 所有原生模塊的初始化
  • 繪制所有的RootView并添加到相應(yīng)實(shí)例并設(shè)置相應(yīng)的監(jiān)聽事件
  • 添加CatalystInstance實(shí)例的內(nèi)存監(jiān)聽事件
  • 設(shè)置React所有相關(guān)實(shí)例初始化完成之后的監(jiān)聽
  • 設(shè)置JS模塊和原生模塊所在線程的優(yōu)先級(jí)

(1) 所有原生模塊的初始化

CatalystInstance catalystInstance =
  Assertions.assertNotNull(reactContext.getCatalystInstance());

catalystInstance.initialize();

追蹤initialize()方法

  /**
   * Initialize all the native modules
   */
  @VisibleForTesting
  @Override
  public void initialize() {
    Log.d(ReactConstants.TAG, "CatalystInstanceImpl.initialize()");
    Assertions.assertCondition(
        !mInitialized,
        "This catalyst instance has already been initialized");
    // We assume that the instance manager blocks on running the JS bundle. If
    // that changes, then we need to set mAcceptCalls just after posting the
    // task that will run the js bundle.
    Assertions.assertCondition(
        mAcceptCalls,
        "RunJSBundle hasn't completed.");
    mInitialized = true;
    mNativeModulesQueueThread.runOnQueue(new Runnable() {
      @Override
      public void run() {
        mNativeModuleRegistry.notifyJSInstanceInitialized();
      }
    });
  }
  /* package */ void notifyJSInstanceInitialized() {
    mReactApplicationContext.assertOnNativeModulesQueueThread("From version React Native v0.44, " +
      "native modules are explicitly not initialized on the UI thread. See " +
      "https://github.com/facebook/react-native/wiki/Breaking-Changes#d4611211-reactnativeandroidbreaking-move-nativemodule-initialization-off-ui-thread---aaachiuuu " +
      " for more details.");
    ReactMarker.logMarker(ReactMarkerConstants.NATIVE_MODULE_INITIALIZE_START);
    Systrace.beginSection(
        Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
        "NativeModuleRegistry_notifyJSInstanceInitialized");
    try {
      for (ModuleHolder module : mModules.values()) {
        module.markInitializable();
      }
    } finally {
      Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
      ReactMarker.logMarker(ReactMarkerConstants.NATIVE_MODULE_INITIALIZE_END);
    }
  }

(2)繪制所有的RootView并添加到相應(yīng)實(shí)例并設(shè)置相應(yīng)的監(jiān)聽事件

 synchronized (mAttachedRootViews) {
      for (ReactRootView rootView : mAttachedRootViews) {
        attachRootViewToInstance(rootView, catalystInstance);
      }
    }

這里的mAttachedRootViewsstartReactApplication()方法中attachToReactInstanceManager()中初始化瓮栗。

  public void startReactApplication(
      ReactInstanceManager reactInstanceManager,
      String moduleName,
      @Nullable Bundle initialProperties) {
    Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "startReactApplication");
    try {
      .............................
      if (!mReactInstanceManager.hasStartedCreatingInitialContext()) {
        mReactInstanceManager.createReactContextInBackground();
      }
      attachToReactInstanceManager();
    } finally {
      Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
    }
  }

追蹤attachToReactInstanceManager()方法,可以看到mAttachedRootViews是在這里add的

  private void attachToReactInstanceManager() {
    Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "attachToReactInstanceManager");
    try {
      if (mIsAttachedToInstance) {
        return;
      }

      mIsAttachedToInstance = true;
      Assertions.assertNotNull(mReactInstanceManager).attachRootView(this);
      getViewTreeObserver().addOnGlobalLayoutListener(getCustomGlobalLayoutListener());
    } finally {
      Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
    }
  }

  /**
   * Attach given {@param rootView} to a catalyst instance manager and start JS application using
   * JS module provided by {@link ReactRootView#getJSModuleName}. If the react context is currently
   * being (re)-created, or if react context has not been created yet, the JS application associated
   * with the provided root view will be started asynchronously, i.e this method won't block.
   * This view will then be tracked by this manager and in case of catalyst instance restart it will
   * be re-attached.
   */
  @ThreadConfined(UI)
  public void attachRootView(ReactRootView rootView) {
    UiThreadUtil.assertOnUiThread();
    mAttachedRootViews.add(rootView);

    // Reset view content as it's going to be populated by the application content from JS.
    rootView.removeAllViews();
    rootView.setId(View.NO_ID);

    // If react context is being created in the background, JS application will be started
    // automatically when creation completes, as root view is part of the attached root view list.
    ReactContext currentContext = getCurrentReactContext();
    if (mCreateReactContextThread == null && currentContext != null) {
      attachRootViewToInstance(rootView, currentContext.getCatalystInstance());
    }
  }

由于createReactContextInBackground()里的代碼通過上面的源碼分析是在一個(gè)單獨(dú)的線程里執(zhí)行削罩,而加載JS端和讀取JSBundle文件都比較耗時(shí),所以mAttachedRootViews并不會(huì)為空费奸,attachRootViewToInstance()一定會(huì)被執(zhí)行弥激,繼續(xù)追蹤attachRootViewToInstance()方法。

  private void attachRootViewToInstance(
      final ReactRootView rootView,
      CatalystInstance catalystInstance) {
    Log.d(ReactConstants.TAG, "ReactInstanceManager.attachRootViewToInstance()");
    Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "attachRootViewToInstance");
    UIManager uiManagerModule = rootView.isFabric() ? catalystInstance.getJSIModule(UIManager.class) : catalystInstance.getNativeModule(UIManagerModule.class);
    final int rootTag = uiManagerModule.addRootView(rootView);
    rootView.setRootViewTag(rootTag);
    rootView.invokeJSEntryPoint();
    Systrace.beginAsyncSection(
      TRACE_TAG_REACT_JAVA_BRIDGE,
      "pre_rootView.onAttachedToReactInstance",
      rootTag);
    UiThreadUtil.runOnUiThread(new Runnable() {
      @Override
      public void run() {
        Systrace.endAsyncSection(
          TRACE_TAG_REACT_JAVA_BRIDGE,
          "pre_rootView.onAttachedToReactInstance",
          rootTag);
        rootView.onAttachedToReactInstance();
      }
    });
    Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
  }

這個(gè)方法比較關(guān)鍵的幾行代碼如下

    UIManager uiManagerModule = rootView.isFabric() ? catalystInstance.getJSIModule(UIManager.class) : catalystInstance.getNativeModule(UIManagerModule.class);
    final int rootTag = uiManagerModule.addRootView(rootView);
    rootView.setRootViewTag(rootTag);
    rootView.invokeJSEntryPoint();
  • 獲取UIManager 愿阐,開始測(cè)量RootView秆撮、給RootView設(shè)置布局監(jiān)聽、把RootView加入UIViewOperationQueue主隊(duì)列
  • 設(shè)置RootViewRootViewTag
  • 調(diào)用JS端入口函數(shù)换况,執(zhí)行JS端代碼

首先我們追蹤invokeJSEntryPoint()方法,可以發(fā)現(xiàn)這個(gè)方法

  /**
   * Calls the default entry point into JS which is AppRegistry.runApplication()
   */
  private void defaultJSEntryPoint() {
      Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "ReactRootView.runApplication");
      try {
        if (mReactInstanceManager == null || !mIsAttachedToInstance) {
          return;
        }

        ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
        if (reactContext == null) {
          return;
        }

        CatalystInstance catalystInstance = reactContext.getCatalystInstance();

        WritableNativeMap appParams = new WritableNativeMap();
        appParams.putDouble("rootTag", getRootViewTag());
        @Nullable Bundle appProperties = getAppProperties();
        if (appProperties != null) {
          appParams.putMap("initialProps", Arguments.fromBundle(appProperties));
        }

        mShouldLogContentAppeared = true;

        String jsAppModuleName = getJSModuleName();
        catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams);
      } finally {
        Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
      }
  }

這里則調(diào)用JS端入口函數(shù)职辨,執(zhí)行JS端代碼,再來追蹤UIManageraddRootView()方法

  /**
   * Registers a new root view. JS can use the returned tag with manageChildren to add/remove
   * children to this view.
   *
   * <p>Note that this must be called after getWidth()/getHeight() actually return something. See
   * CatalystApplicationFragment as an example.
   *
   * <p>TODO(6242243): Make addRootView thread safe NB: this method is horribly not-thread-safe.
   */
  @Override
  public <T extends SizeMonitoringFrameLayout & MeasureSpecProvider> int addRootView(
      final T rootView) {
    Systrace.beginSection(
      Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
      "UIManagerModule.addRootView");
    final int tag = ReactRootViewTagGenerator.getNextRootViewTag();
    final ReactApplicationContext reactApplicationContext = getReactApplicationContext();
    final ThemedReactContext themedRootContext =
      new ThemedReactContext(reactApplicationContext, rootView.getContext());

    mUIImplementation.registerRootView(rootView, tag, themedRootContext);

    rootView.setOnSizeChangedListener(
      new SizeMonitoringFrameLayout.OnSizeChangedListener() {
        @Override
        public void onSizeChanged(final int width, final int height, int oldW, int oldH) {
          reactApplicationContext.runOnNativeModulesQueueThread(
            new GuardedRunnable(reactApplicationContext) {
              @Override
              public void runGuarded() {
                updateNodeSize(tag, width, height);
              }
            });
        }
      });

    Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
    return tag;
  }
  /**
   * Registers a root node with a given tag, size and ThemedReactContext and adds it to a node
   * registry.
   */
  public <T extends SizeMonitoringFrameLayout & MeasureSpecProvider> void registerRootView(
      T rootView, int tag, ThemedReactContext context) {
    final ReactShadowNode rootCSSNode = createRootShadowNode();
    rootCSSNode.setReactTag(tag);
    rootCSSNode.setThemedContext(context);

    int widthMeasureSpec = rootView.getWidthMeasureSpec();
    int heightMeasureSpec = rootView.getHeightMeasureSpec();
    updateRootView(rootCSSNode, widthMeasureSpec, heightMeasureSpec);

    mShadowNodeRegistry.addRootNode(rootCSSNode);

    // register it within NativeViewHierarchyManager
    mOperationsQueue.addRootView(tag, rootView, context);
  }

到了這里RootView已經(jīng)被加入了UIViewOperationQueue,我們進(jìn)而進(jìn)入UIViewOperationQueue源碼查看戈二,發(fā)現(xiàn)有很多關(guān)于視圖更新的方法舒裤。而這邊所有的方法都不會(huì)在這邊直接調(diào)用,需要要通過JS端繪制觉吭,然后進(jìn)一步通知C++端腾供,C++調(diào)用UIManagerModule中的方法對(duì)視圖進(jìn)行刷新、移除鲜滩、創(chuàng)建伴鳖、新增等操作。我們追蹤一個(gè)UIManagerModule創(chuàng)建視圖的方法

  @ReactMethod
  public void createView(int tag, String className, int rootViewTag, ReadableMap props) {
    if (DEBUG) {
      String message =
          "(UIManager.createView) tag: " + tag + ", class: " + className + ", props: " + props;
      FLog.d(ReactConstants.TAG, message);
      PrinterHolder.getPrinter().logMessage(ReactDebugOverlayTags.UI_MANAGER, message);
    }
    mUIImplementation.createView(tag, className, rootViewTag, props);
  }

可以看到這里有一個(gè)rootViewTag而這個(gè)rootViewTag就是之前設(shè)置的RootView的tag徙硅,繼續(xù)追蹤代碼榜聂,可以看到這一個(gè)方法

  /**
   * Handles a createView call. May or may not actually create a native view.
   */
  public void handleCreateView(
      ReactShadowNode node,
      ThemedReactContext themedContext,
      @Nullable ReactStylesDiffMap initialProps) {
    if (!ENABLED) {
      int tag = node.getReactTag();
      mUIViewOperationQueue.enqueueCreateView(
          themedContext,
          tag,
          node.getViewClass(),
          initialProps);
      return;
    }

    boolean isLayoutOnly = node.getViewClass().equals(ViewProps.VIEW_CLASS_NAME) &&
        isLayoutOnlyAndCollapsable(initialProps);
    node.setIsLayoutOnly(isLayoutOnly);

    if (!isLayoutOnly) {
      mUIViewOperationQueue.enqueueCreateView(
          themedContext,
          node.getReactTag(),
          node.getViewClass(),
          initialProps);
    }
  }

在隊(duì)列中創(chuàng)建一個(gè)CreateViewOperation任務(wù)

  public void enqueueCreateView(
      ThemedReactContext themedContext,
      int viewReactTag,
      String viewClassName,
      @Nullable ReactStylesDiffMap initialProps) {
    synchronized (mNonBatchedOperationsLock) {
      mNonBatchedOperations.addLast(
        new CreateViewOperation(
          themedContext,
          viewReactTag,
          viewClassName,
          initialProps));
    }
  }

查看CreateViewOperation源碼

  private final class CreateViewOperation extends ViewOperation {

    private final ThemedReactContext mThemedContext;
    private final String mClassName;
    private final @Nullable ReactStylesDiffMap mInitialProps;

    public CreateViewOperation(
        ThemedReactContext themedContext,
        int tag,
        String className,
        @Nullable ReactStylesDiffMap initialProps) {
      super(tag);
      mThemedContext = themedContext;
      mClassName = className;
      mInitialProps = initialProps;
      Systrace.startAsyncFlow(Systrace.TRACE_TAG_REACT_VIEW, "createView", mTag);
    }

    @Override
    public void execute() {
      Systrace.endAsyncFlow(Systrace.TRACE_TAG_REACT_VIEW, "createView", mTag);
      mNativeViewHierarchyManager.createView(
          mThemedContext,
          mTag,
          mClassName,
          mInitialProps);
    }
  }

繼續(xù)追蹤mNativeViewHierarchyManagercreateView()方法

  public synchronized void createView(
      ThemedReactContext themedContext,
      int tag,
      String className,
      @Nullable ReactStylesDiffMap initialProps) {
    UiThreadUtil.assertOnUiThread();
    SystraceMessage.beginSection(
        Systrace.TRACE_TAG_REACT_VIEW,
        "NativeViewHierarchyManager_createView")
        .arg("tag", tag)
        .arg("className", className)
        .flush();
    try {
      ViewManager viewManager = mViewManagers.get(className);

      View view = viewManager.createView(themedContext, mJSResponderHandler);
      mTagsToViews.put(tag, view);
      mTagsToViewManagers.put(tag, viewManager);

      // Use android View id field to store React tag. This is possible since we don't inflate
      // React views from layout xmls. Thus it is easier to just reuse that field instead of
      // creating another (potentially much more expensive) mapping from view to React tag
      view.setId(tag);
      if (initialProps != null) {
        viewManager.updateProperties(view, initialProps);
      }
    } finally {
      Systrace.endSection(Systrace.TRACE_TAG_REACT_VIEW);
    }
  }

可以看著這里進(jìn)行了視圖的真正的新建疹启,并且標(biāo)記視圖的tag旬渠,后期根據(jù)這個(gè)tag來更新此視圖。

三、作者聯(lián)系方式

作者:郭翰林

GitHub:https://github.com/RmondJone

QQ群:264587303

1537177399680.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末晤锥,一起剝皮案震驚了整個(gè)濱河市香缺,隨后出現(xiàn)的幾起案子衡楞,更是在濱河造成了極大的恐慌充岛,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,423評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拒贱,死亡現(xiàn)場(chǎng)離奇詭異宛徊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)逻澳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,147評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門岩调,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人赡盘,你說我怎么就攤上這事$志荆” “怎么了陨享?”我有些...
    開封第一講書人閱讀 157,019評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)钝腺。 經(jīng)常有香客問我抛姑,道長(zhǎng),這世上最難降的妖魔是什么艳狐? 我笑而不...
    開封第一講書人閱讀 56,443評(píng)論 1 283
  • 正文 為了忘掉前任定硝,我火速辦了婚禮,結(jié)果婚禮上毫目,老公的妹妹穿的比我還像新娘蔬啡。我一直安慰自己,他們只是感情好镀虐,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,535評(píng)論 6 385
  • 文/花漫 我一把揭開白布箱蟆。 她就那樣靜靜地躺著,像睡著了一般刮便。 火紅的嫁衣襯著肌膚如雪空猜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,798評(píng)論 1 290
  • 那天恨旱,我揣著相機(jī)與錄音辈毯,去河邊找鬼。 笑死搜贤,一個(gè)胖子當(dāng)著我的面吹牛谆沃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播仪芒,決...
    沈念sama閱讀 38,941評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼管毙,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼腿椎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起夭咬,我...
    開封第一講書人閱讀 37,704評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤啃炸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后卓舵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體南用,經(jīng)...
    沈念sama閱讀 44,152評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,494評(píng)論 2 327
  • 正文 我和宋清朗相戀三年掏湾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了裹虫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,629評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡融击,死狀恐怖筑公,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情尊浪,我是刑警寧澤匣屡,帶...
    沈念sama閱讀 34,295評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站拇涤,受9級(jí)特大地震影響捣作,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鹅士,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,901評(píng)論 3 313
  • 文/蒙蒙 一券躁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧掉盅,春花似錦也拜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扼脐,卻和暖如春岸军,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瓦侮。 一陣腳步聲響...
    開封第一講書人閱讀 31,978評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工艰赞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人肚吏。 一個(gè)月前我還...
    沈念sama閱讀 46,333評(píng)論 2 360
  • 正文 我出身青樓方妖,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親罚攀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子党觅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,499評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容