React Native startup process detailed analysis

React Native startup process detailed analysis

Introduction: This article takes the sample project (Android part) created by react-native-cli as an example to analyze the startup process of React Native.

The steps for project creation can refer to the official website. The React Native version analyzed in this article is v0.64.2 .

We know that the above project is an Android application. Open the source code file in android/ directory and you will first find that it creates two java files: MainApplication.java and MainActivity.java , which define the application and the main Activity respectively.

The startup process of an Android application is as follows: a globally unique Application object is created before the first activity is started. So here we first analyze MainApplication

MainApplication

public class MainApplication extends Application implements ReactApplication {
  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
        public boolean getUseDeveloperSupport() {
          return BuildConfig.DEBUG;
        }
        @Override
        protected List<ReactPackage> getPackages() {
          @SuppressWarnings("UnnecessaryLocalVariable")
          List<ReactPackage> packages = new PackageList(this).getPackages();
          // Other operations on packages return packages;
        }
        @Override
        protected String getJSMainModuleName() {
          return "index";
        }
  }
  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }
  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
    initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
  }

MainApplication inherits from Application class and implements ReactApplication interface. Things to do include:

1. Create an instance of the member variable ReactNativeHost , and inject some configurations by overriding the ReactNativeHost class method during the creation process, including:

  1. getUseDeveloperSupport: Configure whether to enable debugging
  2. getPackages: configure the modules to load
  3. getJSMainModuleName: configure the entry file name of the js module

2. In onCreate:

  1. Call the Soloader library. Soloader is a so file loading library launched by Facebook. It can handle the dependency of so files. In react-native, all framework-related so files are loaded through SoLoader.
  2. Initialize Flipper through ReactInstanceManager . Flipper is a tool launched by Facebook for debugging iOS, Android, and React Native applications.

Here is a brief introduction to ReactNativeHost and ReactInstanceManager

ReactNativeHost

ReactNativeHost is an abstract class, and developers can override its methods. Its main function is to specify some assignment operations in the application and then obtain an instance of ReactInstanceManager . Therefore, ReactNativeHost can be used as a transit station for assigning user-defined parameters to ReactInstanceManager instances. The core method is: getReactInstanceManager , see below for detailed analysis.

ReactInstanceManager

This class is the core class, which is mainly responsible for managing JS loading, maintaining the life cycle, managing the interaction between JS and C++, and so on. ReactInstanceManager can be understood as a transfer bridge between JS and C++.

MainActivity

Next, look at MainActivity.java :

public class MainActivity extends ReactActivity {
  @Override
  protected String getMainComponentName() {
    return "myProject";
  }
}

Only the getMainComponentName method is overridden in MainActivity class. This class inherits from ReactActivity . Let's look at its ReactActivity .

public abstract class ReactActivity extends AppCompatActivity
    implements DefaultHardwareBackBtnHandler, PermissionAwareActivity {
  private final ReactActivityDelegate mDelegate;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mDelegate.onCreate(savedInstanceState);
  }

ReactActivity fully delegates to ReactActivityDelegate to handle onCreate life cycle. Let's look at ReactActivityDelegate 's onCreate .

protected void onCreate(Bundle savedInstanceState) {
  String mainComponentName = getMainComponentName();
  mReactDelegate =
      new ReactDelegate(
          getPlainActivity(), getReactNativeHost(), mainComponentName, getLaunchOptions()) {
        @Override
        protected ReactRootView createRootView() {
          return ReactActivityDelegate.this.createRootView();
        }
      };
    if (mMainComponentName != null) {
      loadApp(mainComponentName);
    }
  }

Here, the ReactDelegate instance is first created. Next, let's look at loadApp method:

protected void loadApp(String appKey) {
  mReactDelegate.loadApp(appKey);
  getPlainActivity().setContentView(mReactDelegate.getReactRootView());
}

From here we go to the loadApp method of the ReactDelegate instance:

public void loadApp(String appKey) {
  if (mReactRootView != null) {
    throw new IllegalStateException("Cannot loadApp while app is already running.");
  }
  mReactRootView = createRootView();
  mReactRootView.startReactApplication(
      getReactNativeHost().getReactInstanceManager(), appKey, mLaunchOptions);
}

Three things are done here: create rootView ( createRootView ), create ReactInstanceManager ( getReactInstanceManager ), and create ReactApplication ( startReactApplication ).

createRootView

First, let’s take a look at what rootView is.

public class ReactRootView extends FrameLayout implements RootView, ReactRoot { /* ... */}

ReactRootView inherits from FrameLayout and implements RootView and ReactRoot interfaces. FrameLayout is one of the simpler layouts in Android. The entire interface is treated as a blank spare area, and all elements are stacked with the upper left corner aligned. ReactRootView inherits from FrameLayout , indicating that it also exists as a simple layout, and UI 的繪制渲染occur on it.

getReactInstanceManager

ReactInstanceManager is a core class that manages JS loading, C++ and JS interaction, initialization parameters, etc. Finally, the call comes to createReactInstanceManager method in ReactNativeHost class:

protected ReactInstanceManager createReactInstanceManager() {
  ReactInstanceManagerBuilder builder = /* ... */

  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();
  return reactInstanceManager;
}

Here’s what’s happening:

  • Create ReactInstanceManagerBuilder instance. The builder pattern is used here to construct the ReactInstanceManager instance, so the parameters are passed in to set the constructor first;
  • Add all packages registered in ReactNativeHost to the ReactInstanceManagerBuilder instance;
  • If getJSBundleFile is not empty, load the corresponding file, otherwise load the default jsBundleFile ;
  • Call builder.build method. Actually construct ReactInstanceManager instance through the builder

startReactApplication

  public void startReactApplication(/* */) {
    // ...
    try {
      // ...
      mReactInstanceManager.createReactContextInBackground();
    finally
      // ...
    }
  }

Finally, the execution is carried out into the createReactContextInBackground method of ReactInstanceManager . Finally, the call chain is: recreateReactContextInBackgroundInner() -> recreateReactContextInBackgroundFromBundleLoader() -> recreateReactContextInBackground() -> runCreateReactContextOnNewThread()

runCreateReactContextOnNewThread mainly does two things:

  1. Create a new thread and create ReactContext context through createReactContext in the new thread;
  2. The context environment is set up through setupReactContext , and finally AppRegistry.js is called to start the App.

We will put the detailed analysis in another article: React Native startReactApplication process analysis.

Summarize

To summarize this article, we take the sample project (Android part) created by react-native-cli as an example, follow the execution flow of the two classes MainApplication and MainActivity , grasp the main logic, and finally sort out the process of React Native from starting to executing user js files. You can see:

The main function of MainApplication is to pass in the user's configuration and initialize the so library and application debug tools;

The main functions of MainActivity are:

  1. Create a rootView layout container for the application;
  2. Create ReactInstanceManager core class to manage JS loading, C++ and JS interaction, initialization parameters, etc.
  3. ReactContext context is created through startReactApplication , and finally AppRegistry.js is called to start the App.

This is the end of this article about the brief analysis of the React Native startup process. For more relevant React Native startup content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • React native ScrollView pull down refresh effect
  • A brief analysis of React Native startReactApplication method
  • In-depth understanding of React Native custom routing management
  • How to use Lottie animation in React Native project

<<:  Analysis of the principle and creation method of Mysql temporary table

>>:  Solution to the problem of IP loss caused by copying centos8 virtual machine under VMWARE

Recommend

Detailed introduction to JS basic concepts

Table of contents 1. Characteristics of JS 1.1 Mu...

Solve the MySQL login 1045 problem under centos

Since the entire application needs to be deployed...

How to generate PDF and download it in Vue front-end

Table of contents 1. Installation and introductio...

js to realize payment countdown and return to the home page

Payment countdown to return to the home page case...

Detailed process of building mysql5.7.29 on centos7 of linux

1. Download MySQL 1.1 Download address https://do...

How to use Spark and Scala to analyze Apache access logs

Install First you need to install Java and Scala,...

Vue+element+oss realizes front-end fragment upload and breakpoint resume

Pure front-end implementation:切片上傳斷點續傳.斷點續傳needs ...

Solution to the problem of invalid width setting for label and span

By default, setting width for label and span is in...

Example of removing json backslash in php

1. Remove backslashes through the "stripslas...

Tips on HTML formatting and long files for web design

<br />Related articles: 9 practical suggesti...

A brief discussion on the design of Tomcat multi-layer container

Table of contents Container Hierarchy The process...

Summary of 50+ Utility Functions in JavaScript

JavaScript can do a lot of great things. This art...