关于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中 ...
随机推荐
- 【模板】KMP字符串匹配
题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next. (如果你不知道这是什么意思也不要问,去百度 ...
- 洛谷mNOIP模拟赛Day1-分组
传送门 首先是贪心的思路 从后向前选,能多选就多选, 理由:数字越少肯定越优,同时间隔尽量向前推,字典序尽量小 对于K==1,枚举1~512直接判断 对于K==2,需要用镜像并查集,来刻画" ...
- hdu 4352 数位dp + 状态压缩
XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- 【BZOJ3685】【zkw权值线段树】普通van Emde Boas树
原题传送门 因为马上要开始搞树套树了,所以学了一波权值线段树...毕竟是会点zkw线段树的,所以zkw线段树大法好! 解题思路: 介绍一下权值线段树吧,其实感觉就是线段树的本义,就是你用线段树维护了数 ...
- ●BZOJ 2149 拆迁队
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2149 题解: 斜率优化DP,栈维护凸包,LIS,分治(我也不晓得是不是CDQ分治...) 一 ...
- hihiocoder 1255(搜索)(2015ACM/ICPC北京站)
题意: 给你四个矩形,判断能否从中选出3个组成一个矩形 思路: 1.搜索,如果两个能组成一个新的,则将他们合并,继续搜索 2.暴力判断 最开始没注意到3,一直以为要用4个,WR #include &l ...
- bzoj4596[Shoi2016]黑暗前的幻想乡 Matrix定理+容斥原理
4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 464 Solved: 264[Submit][Sta ...
- Linux 基本概念和操作
我们在使用Linux时,不是直接和系统打交道,而是通过shell的中间程序.在图形界面下为了实现窗口的输入和输出,linux系统为我们提供了终端模拟器Terminal,常见的终端模拟器有 gnome- ...
- Python类的定义
Python笔记--类定义 一.类定义: class <类名>: <语句> 类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性 如果直接使用类名修改其属 ...
- P2P技术详解(三):P2P技术之STUN、TURN、ICE详解
1.内容概述 在现实Internet网络环境中,大多数计算机主机都位于防火墙或NAT之后,只有少部分主机能够直接接入Internet.很多时候,我们希望网络中的两台主机能够直接进行通信,即所谓的P2P ...