React Native 启动白屏问题(Android)

参考文章: https://blog.csdn.net/fengyuzhengfan/article/details/52712829
本文主要是针对Android白屏问题,记录解决方案。IOS传送阵。

出现白屏的原因是js.bundle文件未加载完。解决的思路:通过原生代码实现白屏上显示一个Dialog,当js.bundle文件加载完后,在JS代码中将Dialog隐藏。

原生部分

原生部分主要是实现Dialog,显示Dialog和JS调用Dialog隐藏的桥接。原生部分项目结构如下图:


image.png

SplashScreen:创建Diaolg,当白屏的时候显示用。
SplashScreenModule、SplashScreenReactPackage:Dialog关闭的桥接,需要在MainApplication中注册。
welcome.png:Dialog布局文件显示的图片
splash.xml:Dialog加载的布局文件

SplashScreen.java

public class SplashScreen {

    private static int NULL_ID = 0;
    private static Dialog mSplashDialog;
    private static WeakReference mActivity;

    /**
     * 打开启动屏
     */
    public static void show(final Activity activity, final boolean fullScreen, final int themeResId){
        if (activity==null) return;
        mActivity = new WeakReference(activity);
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (!activity.isFinishing()) {
                    mSplashDialog = new Dialog(
                            activity,
                            themeResId !=NULL_ID ? themeResId
                                    : fullScreen ? R.style.SplashScreen_Fullscreen
                                    : R.style.SplashScreen_SplashTheme

                    );
                    mSplashDialog.setContentView(R.layout.splash);
                    mSplashDialog.setCancelable(false);
                    if (!mSplashDialog.isShowing()) {
                        mSplashDialog.show();
                    }
                }
            }
        });
    }

    /**
     * 打开启动屏
     */
    public static void show(final Activity activity, final boolean fullScreen) {
        show(activity, fullScreen, 0);
    }

    /**
     * 打开启动屏
     */
    public static void show(final Activity activity) {
        show(activity, false);
    }

    /**
     * 关闭启动屏
     */
    public static void hide(Activity activity) {
        if (activity == null) {
            if (mActivity == null) {
                return;
            }
            activity = mActivity.get();
        }
        if (activity == null) return;

        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (mSplashDialog != null && mSplashDialog.isShowing()) {
                    mSplashDialog.dismiss();
                    mSplashDialog = null;
                }
            }
        });
    }

}

SplashScreenModule.java

public class SplashScreenModule extends ReactContextBaseJavaModule {
    public SplashScreenModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Override
    public String getName() {
        return "SplashScreen";
    }

    /**
     * 打开启动屏
     */
    @ReactMethod
    public void show() {
        SplashScreen.show(getCurrentActivity());
    }

    /**
     * 关闭启动屏
     */
    @ReactMethod
    public void hide() {
        SplashScreen.hide(getCurrentActivity());
    }

    /**
     * 退出程序
     */
    @ReactMethod
    public void exit() {
        if (getCurrentActivity() != null)
            getCurrentActivity().finish();
        System.exit(0);
    }

}

styles.xml



    
    

    

    
    


MainActivity.java
关键代码:SplashScreen.show(this,true),并且必须在super.onCreate(savedInstanceState)之前调用。

public class MainActivity extends ReactActivity {

    @Override
    protected String getMainComponentName() {
        return "PushDemo";
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        SplashScreen.show(this,true);//显示Dialog
        super.onCreate(savedInstanceState);
        //解决应用程序多次重启问题
        if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0){
            finish();
            return;
        }
    }
}

JS部分

该部分比较简单,直接上代码
SplashNative.js

import {NativeModules, Platform} from 'react-native';

const splash = (Platform.OS === "android") ? NativeModules.SplashScreen : {};

export default splash;

关键点是何时隐藏dialog
在js的第一个页面的componentDidMount方法中调用

    import SplashScreen from '../native/SplashNative'     
    ...
    componentDidMount() {
        if(Platform.OS === 'android') {
            SplashScreen.hide();
        }
    }

到此,就完成了白屏问题的解决。

注:原来npm库中react-native-splash-screen已经解决该问题,其原理一样。

你可能感兴趣的:(React Native 启动白屏问题(Android))