1. 程式人生 > >iOS 實現react-native預載入,優化第一次載入白屏問題

iOS 實現react-native預載入,優化第一次載入白屏問題

專案中存在多個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

單例在程式啟動時初始化。
測試驗證可以發現:記憶體得到優化,白屏問題得到解決。