React Native 启动白屏问题
问题描述:
用React Native架构的无论是Android APP还是iOS APP,在启动时都出现白屏现象,时间大概1~3s(根据手机或模拟器的性能不同而不同)。
问题分析:
为什么会产生白屏?
React Native应用在启动时会将js bundle读取到内存中,并完成渲染。这期间由于js bundle还没有完成装载并渲染,所以界面显示的是白屏。
白屏给人的感觉很不友好,那有没有办法不显示白屏呢?
上文解释了:为什么React Native应用会在启动的时候显示一会白屏。既然知道了出现问题的原因,那么离解决问题也不远了。市场上大部分APP在启动的时候都会有个启动屏,启动屏对于用户是比较友好的,一来展示欢迎信息,二来显示一些产品信息或一些广告,启动页对于程序来说,是为程序完成初始化加载数据,做一些初始化工作的所保留的时间,启动屏等待的时间可长可短,具体根据业务而定。
这里只说下针对iOS的处理方法,也可以直接使用第三方组件react-native-splash-screen。
在iOS中,iOS支持为程序设置一个Launch Image或Launch Screen File来作为启动屏,当程序被打开的时候,首先显示的便是设置的这个启动屏了。
那么小伙伴会问了,这个启动屏幕什么时候会消失呢?
在AppDelegate
如下方法:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
该方法返回一个 BOOL类型的值,当系统调用该方并返回值之后,标志着APP启动加载已经完成,系统会将启动屏给关掉。
所以如果我们控制了这个启动屏幕让它在js bundle加载并渲染完成之后再关闭不就解决了iOS 启动白屏了吗?
上面已经说到,- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
方法执行完成之后,启动屏会被关掉。
所以我们就想办法控制该方实行的时间。
第一步:创建一个名为SplashScreen的Object-C文件
在SplashScreen.h文件中添加如下代码:
#import "RCTBridgeModule.h"
@interface SplashScreen : NSObject<RCTBridgeModule>
+ (void)show;
@end
在SplashScreen.m中添加如下代码:
#import "SplashScreen.h"
static bool waiting = true;
@implementation SplashScreen
- (dispatch_queue_t)methodQueue{
return dispatch_get_main_queue();
}
RCT_EXPORT_MODULE()
//处理白屏问题
+ (void)show {
while (waiting) {
NSDate* later = [NSDate dateWithTimeIntervalSinceNow:0.1];
[[NSRunLoop mainRunLoop] runUntilDate:later];
}
}
RCT_EXPORT_METHOD(hide) {
dispatch_async(dispatch_get_main_queue(),
^{
waiting = false;
});
}
在上述代码中,我们通过[[NSRunLoop mainRunLoop] runUntilDate:later];
来控制- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
方法执行的时间, 主线程会每隔0.1s阻塞一次,直到waiting
变量为true,然后我们就可以通过暴露给JS模块的hide
方法来控制waiting
变量的值,继而达到控制启动屏幕的关闭。
第二步:在JS模块中控制启动屏的关闭
通过第一步我们已经向JS模块暴露了hide
方法,然我们就可以在JS模块中通过hide
方法来关闭启动屏幕。 也就是JS调用原生的方法。
componentDidMount()
{
SplashScreen.hide();
}
原文链接:http://www.devio.org/2016/09/30/React-Native-启动白屏问题解决方案,教程/