关于React Native 安卓首屏白屏优化
问题描述
在android中,当点击某个rn模块的入口按钮,弹出rn的activity到rn的页面展现出来的过程中,会有很明显的白屏现象,不同的机型不同(cpu好的白屏时间短),大概1s到2s的时间。
注意,只有在真机上才会有此现象,在模拟器上没有此现象完全是秒开。
优化分析
ReactRootView mReactRootView = createRootView(); mReactRootView.startReactApplication(mReactInstanceManager, getMainComponentName(), getLaunchOptions());
ReactActivity的onCreate()的完整代码如下:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getUseDeveloperSupport() && Build.VERSION.SDK_INT >= 23) {
// Get permission to show redbox in dev builds.
if (!Settings.canDrawOverlays(this)) {
Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
startActivity(serviceIntent);
FLog.w(ReactConstants.TAG, REDBOX_PERMISSION_MESSAGE);
Toast.makeText(this, REDBOX_PERMISSION_MESSAGE, Toast.LENGTH_LONG).show();
}
}
mReactInstanceManager = createReactInstanceManager();
ReactRootView mReactRootView = createRootView();
mReactRootView.startReactApplication(mReactInstanceManager, getMainComponentName(), getLaunchOptions());
setContentView(mReactRootView);
}
知道了产生问题的原因,我们就知道怎么着手优化了。我们首先想到的:-内存换时间
步骤一:
缓存rootview管理器主要用于初始化和缓存rootview对象。
import android.app.Activity;
import android.os.Bundle;
import android.view.ViewParent;
import com.facebook.react.LifecycleState;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactPackage;
import com.facebook.react.ReactRootView;
import java.lang.reflect.Field;
/**
* 缓存view管理
*/
public class RNCacheViewManager {
private static ReactRootView mRootView = null;
private static ReactInstanceManager mManager = null;
private static AbsRnInfo mRnInfo = null;
//初始化
public static void init(Activity act, AbsRnInfo rnInfo) {
init(act, rnInfo, null);
}
public static void init(Activity act, AbsRnInfo rnInfo, Bundle launchOptions) {
if (mManager == null) {
updateCache(act, rnInfo, launchOptions);
}
}
public static void updateCache(Activity act, AbsRnInfo rnInfo) {
updateCache(act, rnInfo, null);
}
//更新cache,适合于版本升级时候更新cache
public static void updateCache(Activity act, AbsRnInfo rnInfo, Bundle launchOptions) {
mRnInfo = rnInfo;
mManager = createReactInstanceManager(act);
mRootView = new ReactRootView(act);
mRootView.startReactApplication(mManager, rnInfo.getMainComponentName(), launchOptions);
}
//设置模块名称,因为是private,只能通过反射赋值
public static void setModuleName(String moduleName) {
try {
Field field = ReactRootView.class.getDeclaredField("mJSModuleName");
field.setAccessible(true);
field.set(getReactRootView(), moduleName);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
//设置启动参数,因为是private,只能通过反射赋值
public static void setLaunchOptions(Bundle launchOptions) {
try {
Field field = ReactRootView.class.getDeclaredField("mLaunchOptions");
field.setAccessible(true);
field.set(getReactRootView(), launchOptions);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
public static ReactRootView getReactRootView() {
if(mRootView==null){
throw new RuntimeException("缓存view管理器尚未初始化!");
}
return mRootView;
}
public static ReactInstanceManager getReactInstanceManager() {
if(mManager==null){
throw new RuntimeException("缓存view管理器尚未初始化!");
}
return mManager;
}
public static AbsRnInfo getRnInfo() {
if(mRnInfo==null){
throw new RuntimeException("缓存view管理器尚未初始化!");
}
return mRnInfo;
}
public static void onDestroy() {
try {
ViewParent parent = getReactRootView().getParent();
if (parent != null)
((android.view.ViewGroup) parent).removeView(getReactRootView());
} catch (Throwable e) {
e.printStackTrace();
}
}
public static void clear() {
try {
if (mManager != null) {
mManager.onDestroy();
mManager = null;
}
if (mRootView != null) {
onDestroy();
mRootView = null;
}
mRnInfo = null;
} catch (Throwable e) {
e.printStackTrace();
}
}
private static ReactInstanceManager createReactInstanceManager(Activity act) {
ReactInstanceManager.Builder builder = ReactInstanceManager.builder()
.setApplication(act.getApplication())
.setJSMainModuleName(getRnInfo().getJSMainModuleName())
.setUseDeveloperSupport(getRnInfo().getUseDeveloperSupport())
.setInitialLifecycleState(LifecycleState.BEFORE_RESUME);
for (ReactPackage reactPackage : getRnInfo().getPackages()) {
builder.addPackage(reactPackage);
}
String jsBundleFile = getRnInfo().getJSBundleFile();
if (jsBundleFile != null) {
builder.setJSBundleFile(jsBundleFile);
} else {
builder.setBundleAssetName(getRnInfo().getBundleAssetName());
}
return builder.build();
}
}
步骤二
重写ReactActivity,可以拷贝出来改,也可以继承写,主要是重写onCreate和onDestroy,其余代码不动。onCreate方法中使用缓存rootview管理器来获得rootview对象,而不是重新创建。
onCreate()代码
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (RNCacheViewManager.getRnInfo().getUseDeveloperSupport() && Build.VERSION.SDK_INT >= 23) {
// Get permission to show redbox in dev builds.
if (!Settings.canDrawOverlays(this)) {
Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
startActivity(serviceIntent);
FLog.w(ReactConstants.TAG, REDBOX_PERMISSION_MESSAGE);
Toast.makeText(this, REDBOX_PERMISSION_MESSAGE, Toast.LENGTH_LONG).show();
}
}
mReactInstanceManager = RNCacheViewManager.getReactInstanceManager();
ReactRootView mReactRootView = RNCacheViewManager.getReactRootView();
setContentView(mReactRootView);
}
onDestroy方法中,不能再调用原有的mReactInstanceManager.destroy()方法了,否则rn初始化出来的对象会被销毁,下次就用不了了。同时,要卸载掉rootview的parent对象,否则下次再setContentView时候回报错。
protected void onDestroy() {
RNCacheViewManager.onDestroy();
super.onDestroy();
}
public static void onDestroy() {
try {
ViewParent parent = getReactRootView().getParent();
if (parent != null)
((android.view.ViewGroup) parent).removeView(getReactRootView());
} catch (Throwable e) {
e.printStackTrace();
}
}
步骤三
RNCacheViewManager.init((Activity) context, new RnInfo(moduleName, launchOptions));
RnInfo实体类代码:
public class RnInfo extends AbsRnInfo {
private String mModuleName;
private Bundle mLaunchOptions;
public RnInfo(String moduleName) {
this.mModuleName = moduleName;
}
public RnInfo(String moduleName, Bundle launchOptions) {
this.mModuleName = moduleName;
this.mLaunchOptions = launchOptions;
}
@Nullable
@Override
public Bundle getLaunchOptions() {
return mLaunchOptions;
}
@Override
public String getMainComponentName() {
return mModuleName;
}
@Override
public String getJSMainModuleName() {
return RNKeys.Default.DEf_JS_MAIN_MODULE_NAME;
}
@Nullable
@Override
public String getJSBundleFile() {
return RNManager.getJsBundlePath();
}
@Override
public boolean getUseDeveloperSupport() {
return true;
}
@Override
public List<ReactPackage> getPackages() {
return Arrays.asList(
new MainReactPackage(),
new BBReactPackage()
);
}
}
关于React Native 安卓首屏白屏优化的更多相关文章
- React Native 首次加载白屏优化
RN首次加载都会有个白屏过程,一般都会有500ms+的白屏时间,原生页面开发同样的页面会能够快速显示而在RN页面中有个明显的等待过程,这个会影响用户体验. 1.使用过渡页面 简单处理可以在白屏过程中加 ...
- react native 完美解决启动白屏
先讲下我的RN版本0.58.5 首先安装react-native-splash-screen(目前使用的版本是3.2.0) 项目地址https://github.com/crazycodeboy/re ...
- Android 启动APP时黑屏白屏的三个解决方案
你会很奇怪,为什么有些app启动时,会出现一会儿的黑屏或者白屏才进入Activity的界面显示,但是有些app却不会如QQ手机端,的确这里要做处理一下.这里先了解一下为什么会出现这样的现象,其实很简单 ...
- Android 启动APP时黑屏白屏的三个解决方案(转载)
你会很奇怪,为什么有些app启动时,会出现一会儿的黑屏或者白屏才进入Activity的界面显示,但是有些app却不会如QQ手机端,的确这里要做处理一下.这里先了解一下为什么会出现这样的现象,其实很简单 ...
- react history模式下的白屏问题
近期,再用react的时候,由于不想用丑陋的hash,便将路由模式切换成history了,结果带来了一些问题,比如刷新白屏,还有图片加载不出来,这里我们说一下解决方案. 原因 首先,我们说一下造成这一 ...
- Android -- 距离感应器控制屏幕灭屏白屏
权限 <u ...
- Android 启动APP时黑屏白屏的解决方案
在开发中,我们在启动app的时候,屏幕会出现一段时间的白屏或者黑屏,不同设备时间长短不同.很影响用户体验. 首先分析一下,产生这个现象的原因,当我们在启动一个应用时,系统会去检查是否已经存在这样一个进 ...
- 配置React Native 安卓开发环境
配置主要分为以下几步: 安装node.js 安装AndroidStudio 安装React Native命令行工具 搭建React Native版本的Hello World,修改代码查看效果 第一步 ...
- React Native 安卓 程序运行报错: React Native version mismatch(转载)
这个问题已经得到解决,参照stackoverflow上的问题:https://stackoverflow.com/que...这个问题的原因就处在Android工程中app/build.gradle中 ...
随机推荐
- Fliptile 翻格子游戏
问题 B: [Usaco2007 Open]Fliptile 翻格子游戏 时间限制: 5 Sec 内存限制: 128 MB 题目描述 Farmer John knows that an intell ...
- ●HDU 5608 function
题链: http://acm.hdu.edu.cn/showproblem.php?pid=5608 题解: 莫比乌斯反演,杜教筛 已知$$N^2-3N+2=\sum_{d|N} f(d)$$ 多次询 ...
- hdu 3939(勾股+容斥)
题意: 给定一个整数L(L<=1e12),计算(x,y,z)组的个数.其中x<y<z,x^2+y^2=z^2,gcd(x,y)==1,gcd(x,z)==1,gcd(y,z)==1. ...
- POJ2187Beauty Contest 旋转卡壳
题目链接 http://poj.org/problem?id=2187 先求凸包 再求凸多边形直径 旋转卡壳模板题 #include<cstdio> #include<cstring ...
- 零开始:NetCore项目权限管理系统:基础框架搭建
有兴趣的同学可以一起做 喜欢NetCore的朋友,欢迎加群QQ:86594082 源码地址:https://github.com/feiyit/SoaProJect 新建一个空的解决方案,建立对应的解 ...
- c语言程序第2次作业
(一)改错题 1.输出带框文字:在屏幕上输出以下3行信息. 错误信息1:{{uploading-image-560144.png(uploading...)} 错误原因:stdio误写为stido 错 ...
- VMWare 学习目录
Linux介绍 Linux入门--个人感想 Google怎么用linux 初入Linux Windows XP硬盘安装Ubuntu 12.04双系统图文详解 实例讲解虚拟机3种网络模式(桥接.nat. ...
- @RequestBody和@RequestParam区别
@RequestParam 用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容.(Http协议中,默认传递的参数就是applicati ...
- 列表ListBox、ListView、GridView 排序
列表排序 1.使用控件默认排序方式(推荐) ListControl.Items.SortDescriptions.Clear(); ListControl.Items.SortDescriptions ...
- git遇到的问题
push代码时出现的问题: ! [remote rejected] HEAD -> (unpacker error)) 解决办法: $ git push --no-thin origin rel ...