[React Native] Android 白屏優化
阿新 • • 發佈:2019-01-28
APP是原生嵌入一個React Native介面
背景
按官方例項集成了一個React Native介面,但每次開啟都感覺等待時間有點長,會有白屏狀態。這對於強迫症來說簡直不能忍。於是決定優化。
效果
優化前的效果,白屏時間較長。
優化後,白屏時間明顯變短。
原因
當Android要執行React Native時,需要先載入JSBundle,這塊是比較耗時的。
之前的做法是在開啟介面的時候才去載入,所以會慢一拍。
優化之後,在App啟動時,就初始化JSBundle,然後在RN介面直接使用。
解決方案
建立一個RN載入器的單利
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Bundle;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactInstanceManagerBuilder;
import com.facebook.react.ReactRootView;
import com.facebook.react.common.LifecycleState;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.prance.lib.react.pack.MyReactPackage;
/**
* JSBundle載入唯一例項
* <p>
* Created by bingbing on 2017/5/9.
*/
public class MyReactInstanceManager {
private static MyReactInstanceManager mInstance;
private ReactInstanceManager mReactInstanceManager;
public static MyReactInstanceManager getInstance() {
if (mInstance == null) {
synchronized (MyReactInstanceManager.class) {
if (mInstance == null) {
mInstance = new MyReactInstanceManager();
}
}
}
return mInstance;
}
/**
* 初始化
*
* @param context
*/
public void init(Context context) {
getReactInstanceManager(context);
}
/**
* 初始化 ReactInstanceManager
* 預載入jsBundle
* @param context
* @return
*/
public ReactInstanceManager getReactInstanceManager(Context context) {
Application application = (Application) context.getApplicationContext();
if (mReactInstanceManager == null) {
ReactInstanceManagerBuilder builder = ReactInstanceManager.builder()
.setApplication(application)
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("index.android")
.setUseDeveloperSupport(false)
.addPackage(new MyReactPackage());
//這裡注意!!一定要是LifecycleState.BEFORE_CREATE
//這樣當正式載入的時候,才可以獲取到mCurrentActivity的引用
builder.setInitialLifecycleState(LifecycleState.BEFORE_CREATE);
mReactInstanceManager = builder.build();
//預載入!!!
mReactInstanceManager.createReactContextInBackground();
}
return mReactInstanceManager;
}
/**
* 開啟開發者選單
*/
public void showDevOptionsDialog() {
mReactInstanceManager.showDevOptionsDialog();
}
/**
* 返回鍵
*/
public void onBackPressed() {
mReactInstanceManager.onBackPressed();
}
/**
* 在Activity的onResume中呼叫
* @param activity
* @param handler
*/
public void onHostResume(Activity activity, DefaultHardwareBackBtnHandler handler) {
mReactInstanceManager.onHostResume(activity, handler);
}
/**
* 在Activity的onPause中呼叫
*
* @param activity
*/
public void onHostPause(Activity activity) {
mReactInstanceManager.onHostPause(activity);
}
/**
* 建立ReactRootView例項,並啟動React Native
* @param context
* @param initialProps
* @return
*/
public ReactRootView getRootView(Context context, Bundle initialProps) {
ReactRootView view = new ReactRootView(context);
view.startReactApplication(mReactInstanceManager, "App", initialProps);
return view;
}
/**
* 銷燬RootView,在Activity的onDestroy中呼叫
* @param view
*/
public void destroy(ReactRootView view) {
mReactInstanceManager.detachRootView(view);
}
/**
* 銷燬Manager,在程式退出或者最後一個RN介面結束時呼叫
*/
public void destroy() {
mReactInstanceManager.onHostDestroy();
}
}
初始化
- 在Application或者第一個介面呼叫
MyReactInstanceManager.getInstance().init(this);
- 在Activity中呼叫
ReactRootView rootView = MyReactInstanceManager.getInstance().getRootView(mActivity, initialProps);
setContentView(rootView);