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-启动白屏问题解决方案,教程/

posted @ 2018-06-22 10:46  梅子~  阅读(1229)  评论(0编辑  收藏  举报