iOS 實現react-native預載入,優化第一次載入白屏問題
阿新 • • 發佈:2019-01-01
專案中存在多個react-native頁面入口,每個入口使用以下方法初始化:
- (instancetype)initWithBundleURL:(NSURL *)bundleURL
moduleName:(NSString *)moduleName
initialProperties:(NSDictionary *)initialProperties
launchOptions:(NSDictionary *)launchOptions;
但在除錯中發現兩個現象:
1.重複進入react-native頁面、退出react-native頁面的操作,RCTBridge物件會被重複建立、銷燬。有時候RCTBridge物件未能及時建立還會crash
2.在原生頁面和react-native頁面相互跳轉是RCTBridge也會被重複建立,造成很大的記憶體開銷
帶著疑問去閱讀RCTRootView.h發現一些細節:
/**
* - Designated initializer -
*/
- (instancetype)initWithBridge:(RCTBridge *)bridge
moduleName:(NSString *)moduleName
initialProperties:(NSDictionary *)initialProperties NS_DESIGNATED_INITIALIZER;
/**
* - Convenience initializer -
* A bridge will be created internally.
* This initializer is intended to be used when the app has a single RCTRootView,
* otherwise create an `RCTBridge` and pass it in via `initWithBridge:moduleName:`
* to all the instances.
*/
- (instancetype)initWithBundleURL:(NSURL *)bundleURL
moduleName:(NSString *)moduleName
initialProperties:(NSDictionary *)initialProperties
launchOptions:(NSDictionary *)launchOptions;
可以看到專案中使用多個RCTRootView時,推薦使用以下方法初始化:
- (instancetype) initWithBridge:(RCTBridge *)bridge
moduleName:(NSString *)moduleName
initialProperties:(NSDictionary *)initialProperties NS_DESIGNATED_INITIALIZER;
通過上述的兩個現象和推薦的初始化API,很自然的可以想到使用單例初始化一個bridge物件解決上述問題:
//.h
@interface BridgeManager: RCTBridge
+ (BridgeManager*)shareInstance;
@end
@interface BridgeHandle : NSObject<RCTBridgeDelegate>
@end
//.m
implementation MallBridgeHandle
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
return [[NSBundle mainBundle] URLForResource:@"index.ios" withExtension:@"jsbundle"];
}
@end
@implementation BridgeManager
static BridgeManager * manager = nil;
static dispatch_once_t onceToken;
+ (BridgeManager*)shareInstance
{
dispatch_once(&onceToken,^{
manager = [BridgeManager alloc] initWithDelegate:[[BridgeHandle alloc] init] launchOptions:nil];
});
return manager ;
}
@end
單例在程式啟動時初始化。
測試驗證可以發現:記憶體得到優化,白屏問題得到解決。