directory

  • Problem description
  • Problem analysis
  • Android starts the white screen solution
  • IOS starts the white screen solution
  • Open source library
  • The last

React-native splash-screen

Problem Description:

Both Android and iOS apps that use the React Native architecture display a blank screen at startup for about 1 to 3s (depending on the performance of the phone or emulator).

Problem analysis:

Why is there a blank screen?

React Native reads the JS bundle into memory when it starts and renders it. During this time, the JS bundle has not been loaded and rendered, so the screen is blank.

A white screen feels unfriendly, but is there a way not to display it?

Here’s why React Native displays a blank screen when it starts up. Now that we know the cause of the problem, we are not far away from solving it. Most of the APP is launched on the market when there’s a startup screen, start screen is more friendly for users, which show welcome message, and show some product information or some advertising, start page for program is for initialization program to complete loading the data, the retained time to do some initialization, startup screen waiting time can be long or short, It depends on the business.

Here’s how to add a startup screen to React Native and fix the problem.

Android starts the white screen solution

We can fix the problem by adding a startup screen to React Native Android apps. In “React Native Android Startup Screen, Start White screen, Flash white Screen”, I describe a good way to add a startup screen to React Native Android apps. However, this method involves modifying the React Native source code. If the React Native version is updated, it will require some processing of the source code, so it will not be easy to maintain in the future.

Here’s another way to add a startup screen to React Native Android apps.

In React Native Android Startup Screen, Start white Screen, Flash white screen, we used to add a view to the root view container as the startup screen. After the JS bundle is loaded and rendered, the added view is removed from the root view. The way we add a view to the root view is to block out the white screen, and since it’s blocking out the white screen, can we pop up a dialog box?

You might say that the dialog box is not full screen, and the theme is different, but that’s ok, since we can add dialog boxes, we can modify the style of the dialog box to achieve the desired effect.

What kind of effect do we need to have in order to achieve the effect of the launch screen?

  1. Display when the APP starts;
  2. Disappears after the JS bundle is loaded and rendered.
  3. Full screen display;
  4. The content displayed can be modified using the Layout XML;

These are our basic requirements for this dialog. Let’s implement them now:

First, create a dialog box componentSplashScreen

To meet the above requirements, the dialog box component needs to provide the following two methods:

1. Display dialog box method:

Public static void show(final Activity Activity,final Boolean fullScreen) {if (Activity == null) return;  mActivity = new WeakReference(activity); activity.runOnUiThread(new Runnable() { @Override public void run() { if (! activity.isFinishing()) { mSplashDialog = new Dialog(activity,fullScreen? R.style.SplashScreen_Fullscreen:R.style.SplashScreen_SplashTheme); mSplashDialog.setContentView(R.layout.launch_screen); mSplashDialog.setCancelable(false); if (! mSplashDialog.isShowing()) { mSplashDialog.show(); }}}}); }Copy the code

In order for the Activity to be destroyed, the Activity held can be recycled in time, here we use new WeakReference(Activity); A weak reference to the Activity is created.

Also, because in Android all UI operations must be in the main thread, so we pass activity.runonuithRead (new Runnable()… , put the display of the dialog box in the main thread processing.

In the code above, the second argument to show fullScreen indicates that the boot screen is fullScreen (that is, whether to hide the status bar), SplashScreen_Fullscreen and R.Style.splashScreen_splashTheme are used to hide the state.

We can then call the void show(final Activity Activity,final Boolean fullScreen) method in the onCreate method of mainActivity.java to display the boot screen.

@Override
protected void onCreate(Bundle savedInstanceState) {
    SplashScreen.show(this,true);
    super.onCreate(savedInstanceState);
}
Copy the code

Tip: SplashScreen. Show (this, true); On super. OnCreate (savedInstanceState); The previous position would have worked better.

2. Close the dialog box:

Public static void hide(Activity Activity) {if (Activity == null) Activity = mactivity.get (); if (activity == null) return; activity.runOnUiThread(new Runnable() { @Override public void run() { if (mSplashDialog ! = null && mSplashDialog.isShowing()) { mSplashDialog.dismiss(); }}}); }Copy the code

In the code above, we provide a way to turn off the startup screen. How do YOU make the JS module call void hide(Activity Activity) to close the boot screen?

Step 2: Provide to the JS moduleSplashScreencomponent

Because we need to call the hide method in js and control the closing of the startup screen. Js cannot directly call Java, so we need to build a bridge for them (Native Modules).

First, create oneReactContextBaseJavaModuleType for js calls.

/** * SplashScreenModule * http://www.cboy.me * GitHub:https://github.com/crazycodeboy * Eamil:[email protected] */ public class SplashScreenModule extends ReactContextBaseJavaModule{ public SplashScreenModule(ReactApplicationContext reactContext) {  super(reactContext); } @Override public String getName() { return "SplashScreen"; } / / @reactMethod public void show() {splashscreen.show (); @reactMethod public void hide() {splashscreen.hide ()); }}Copy the code

Next, create oneReactPackageType class to register our React NativeSplashScreenModuleComponents.

/** * SplashScreenReactPackage http://www.cboy.me * GitHub:https://github.com/crazycodeboy * Eamil:[email protected] */ public class SplashScreenReactPackage implements ReactPackage { @Override public List> createJSModules() { return Collections.emptyList(); } @Override public List createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } @Override public List createNativeModules( ReactApplicationContext reactContext) { List modules = new ArrayList<>(); modules.add(new SplashScreenModule(reactContext)); return modules; }}Copy the code

Again, register in MainApplicationSplashScreenModuleComponents.

@Override protected List getPackages() { return Arrays.asList( new MainReactPackage(), new SplashScreenReactPackage() );  }Copy the code

With that done, we can now close the boot screen by calling the hide method in JS.

Step 3: Close the startup screen in the JS module

Create a file called SplashScreen and add the following code.

/** * SplashScreen * http://www.cboy.me * GitHub:https://github.com/crazycodeboy * Eamil:[email protected] * @flow */ 'use strict'; import { NativeModules } from 'react-native'; module.exports = NativeModules.SplashScreen;Copy the code

We can then turn off the boot screen by calling the hide() method of SplashScreen in JS.

componentDidMount() {
    SplashScreen.hide();
}
Copy the code

Don’t forget to import SplashScreen from ‘./SplashScreen in the js file that uses SplashScreen.

IOS starts the white screen solution

In iOS, iOS supports setting a Launch Image or Launch Screen File for the program as the Launch Screen. When the program is opened, the Launch Screen will be displayed first.

When will the startup screen disappear?

The AppDelegate method looks like this:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

This method returns a value of type BOOL. When the system calls this method and returns the value, it indicates that APP startup loading has completed and the system will turn off the startup screen.

So if we control the startup screen and let it close after the JS bundle is loaded and rendered, wouldn’t that solve the iOS startup blank screen?

As it says, – (BOOL) application: (UIApplication *) application didFinishLaunchingWithOptions: (NSDictionary *) launchOptions method execution is completed, The boot screen will be turned off.

So we try to control the timing of their implementation.

Step 1: Create a file namedSplashScreenObject – C files

Add the following code to the splashscreen.h file:

// // splashscreen. h // SplashScreen // from: http://www.cboy.me // GitHub:https://github.com/crazycodeboy // Eamil:[email protected] #import "RCTBridgeModule.h"  @interface SplashScreen : NSObject + (void)show; @endCopy the code

Add the following code to splashscreen.m:

// SplashScreen http://www.cboy.me // GitHub:https://github.com/crazycodeboy // Eamil:[email protected] #import "SplashScreen.h" static bool waiting = true; @implementation SplashScreen - (dispatch_queue_t)methodQueue{ return dispatch_get_main_queue(); Show {} RCT_EXPORT_MODULE () + (void) while (waiting) {NSDate * later = [NSDate dateWithTimeIntervalSinceNow: 0.1]; [[NSRunLoop mainRunLoop] runUntilDate:later]; } } RCT_EXPORT_METHOD(hide) { dispatch_async(dispatch_get_main_queue(), ^{ waiting = false; }); } @endCopy the code

In the above code, we use [[NSRunLoop mainRunLoop] runUntilDate:later]; To control – (BOOL) application: (UIApplication *) application didFinishLaunchingWithOptions: (NSDictionary *) launchOptions method execution time, The main thread will block every 0.1s until the waiting variable is true, and then we can control the value of waiting variable by exposing the hide method to the JS module, so as to control the closing of the startup screen.

Step 2: Close the startup screen in the JS module

Now that we’ve exposed the hide method to the JS module in the first step, we can use the hide method to close the startup screen in the JS module. Because iOS in JS module to control the closing of the startup screen and Android in the third step: in the JS module to control the closing of the startup screen is the same, here will not be introduced.

Open source library

In order to facilitate the use of React Native and solve the problem of blank screen when the React Native app starts, I have made the above solution into the React Native component, React-Native -splash- Screen, which is open source on GitHub for users to download and use.

The last

Now that I have come, please leave me a favor and encourage me to continue to create

If you like my articles, follow mineblogCome on, let’s be friends

Click here and follow:

GitHub: My open source project