Detailed analysis of React Native startup process

  • 2021-11-13 00:22:39
  • OfStack

Introduction: This article is based on react-native-cli The example project created (Android part) is taken as an example to analyze the startup process of React Native.

Please refer to official website for project creation steps. The analysis of this paper React Native Version is v0.64.2 .

We know that the above project is an Android application, open it android/ Directory source code files, first found that it created two java files: MainApplication.java And MainActivity.java The application and main Activity are defined respectively.

The startup process of Android application is as follows: After starting the first activity A globally only 1 is created before Application Object. Therefore, 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 pairs  packages  Operation of 
          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 the Application class and implements the React Native0 Interface. Among the things done are:

1. Create member variables React Native1 And inject 1 configuration during creation by overriding the ReactNativeHost class method, including:

getUseDeveloperSupport: Configure whether debugging is on getPackages: Configure the module to load getJSMainModuleName: Configure the entry file name of the js module

2. In onCreate:

Call the Soloader library. React Native2 Is an so file loading library introduced by facebook, which can handle the dependency of so files. In react-native, all framework-related so files are loaded through SoLoader Pass React Native3 Initialize Flipper. React Native4 It is a tool introduced by facebook for debug ios, Android, React Native applications.

Here is a brief introduction React Native1 And React Native3

ReactNativeHost

React Native1 Is an abstract class, and developers can override the methods in it. Its main function is to specify 1 assignment operation in application, and then get React Native3 Gets or sets an instance of the. So you can put React Native1 As a way to assign user-defined parameters to React Native3 The staging station for the instance. The core approach is: v0.64.21 For a detailed analysis, see below.

ReactInstanceManager

This class is the core class, which is mainly responsible for managing the loading of JS, maintaining the life cycle, managing the interaction between JS and C + +, and so on. You can put React Native3 It is understood as the transit bridge between JS and C + +.

MainActivity

Keep looking MainActivity.java :


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

v0.64.24 Only the getMainComponentName method is overridden in the. This class inherits from v0.64.25 Let's look at it again v0.64.25 .


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);
  }

v0.64.25 Entrust with full authority v0.64.28 To deal with v0.64.29 Life cycle. Come and see v0.64.28 Adj. v0.64.29 .


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);
    }
  }

The ReactDelegate instance is first created here. Let's take a look android/2 Methods:


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

From this to ReactDelegate Instance of the android/2 Methods:


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 ), creating ReactInstanceManager ( v0.64.21 ), creating ReactApplication ( startReactApplication ).

createRootView

First, look at what rootView is.


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

ReactRootView inherits from FrameLayout And implements the RootView , ReactRoot Two interfaces. FrameLayout It is one of the simpler layouts of Android. The whole interface is regarded as a blank spare area, and all elements are aligned and stacked in the upper left corner. ReactRootView inherits from FrameLayout Which indicates that it also exists as a simple layout, UI 的绘制渲染 It all happened up there.

getReactInstanceManager

React Native3 Is a core class, which manages the loading of JS, the interaction between C + + and JS, initialization parameters, etc. The final call comes React Native1 Class in the createReactInstanceManager Methods:


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;
}

The things done here are as follows:

Create ReactInstanceManagerBuilder Instance. Here, the builder mode is used to construct React Native3 Instance, so pass the parameter setting constructor here first; Put in React Native1 Registered in MainActivity.java0 Add to ReactInstanceManagerBuilder Instance; If MainActivity.java2 Is not empty, the corresponding file is loaded; Otherwise, the default MainActivity.java3 ; Call MainActivity.java4 Method. Through the real construction of the builder React Native3 Instances

startReactApplication


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

Final execution to React Native3 Adj. MainActivity.java7 Method. Finally, through the call chain: MainActivity.java8

MainActivity.java9 I mainly did two things:

Create a new thread and pass the activity0 Create activity1 Context; Pass activity2 To set the context, and finally call the activity3 Start App.

Detailed analysis is put into another article: React Native startReactApplication process combing.

Summarize

Summarize this article and pass react-native-cli Create a sample project (Android part) as an example, following two classes MainApplication And v0.64.24 The execution process, grasping the backbone logic, and finally combing out React Native From Start to Execute User activity8 File process. You can see:

MainApplication The main function is to pass in the user configuration and do Application0 Libraries and Applications Application1 Initialization of tools;

v0.64.24 The main functions are:

Create for the application rootView Layout container; Create React Native3 Core class, which is used to manage the loading of JS, the interaction between C + + and JS, initialization parameters, etc.; Pass startReactApplication To create activity1 Context, and eventually calls the activity3 Start App.

Related articles: