React Native应用通过codePush.restartApp重启后白屏问题求助
解决CodePush重启后React Native应用的白屏问题
问题场景
通过CodePush完成更新安装后,调用codePush.restartApp(true)强制重启React Native应用,重启瞬间会出现1秒左右的白屏,随后才显示react-native-bootsplash的启动屏。
提供的相关代码
let intervalId: NodeJS.Timeout | undefined; const codePushSyncCallback = (status: codePush.SyncStatus) => { switch (status) { case codePush.SyncStatus.CHECKING_FOR_UPDATE: { rootStore.userStorage.setIsShowProgressBar(false); rootStore.userStorage.setUpdateStatus(status); setStatus(status); break; } case codePush.SyncStatus.UP_TO_DATE: { rootStore.userStorage.setIsShowProgressBar(false); rootStore.userStorage.setUpdateStatus(status); setStatus(status); rootStore.userStorage.setUpdateProgress(50); intervalId = setInterval(async () => { if (rootStore.userStorage.updateProgress === 100) { if (Platform.OS === 'android') { await changeNavigationBarColor(WHITE, true, true); } rootStore.userStorage.setIsShowUpdateProgress(false); return; } rootStore.userStorage.setUpdateProgress(rootStore.userStorage.updateProgress + 10); }, 500); break; } case codePush.SyncStatus.DOWNLOADING_PACKAGE: { rootStore.userStorage.setIsShowProgressBar(true); rootStore.userStorage.setIsShowUpdateProgress(true); rootStore.userStorage.setUpdateStatus(status); if (Platform.OS === 'android') { changeNavigationBarColor(CUSTOM_BLUE, true, true); } setStatus(status); break; } case codePush.SyncStatus.INSTALLING_UPDATE: { rootStore.userStorage.setUpdateStatus(status); setStatus(status); break; } case codePush.SyncStatus.UPDATE_INSTALLED: { rootStore.userStorage.setUpdateStatus(status); setStatus(status); rootStore.userStorage.setIsShowProgressBar(false); rootStore.userStorage.setIsShowUpdateProgress(false); codePush.allowRestart(); codePush.restartApp(true); break; } case codePush.SyncStatus.UNKNOWN_ERROR: { rootStore.userStorage.setIsShowProgressBar(false); rootStore.userStorage.setUpdateStatus(status); rootStore.userStorage.setIsShowUpdateProgress(false); if (Platform.OS === 'android') { changeNavigationBarColor(CUSTOM_BLUE, true, true); } setStatus(status); break; } default: { break; } } }; codePush.sync( codePushOptions, codePushSyncCallback, (progress) => { const percentage = Math.floor((progress.receivedBytes / progress.totalBytes) * 100); rootStore.userStorage.setUpdateProgress(percentage); setProgress(percentage); } );
解决方案
1. RN层添加过渡启动屏(最直接有效)
白屏核心原因是CodePush重启时,原RN界面已销毁,但原生启动屏尚未立即显示,出现视觉空档。我们可以在重启前先渲染一个和react-native-bootsplash完全一致的全屏组件,覆盖当前界面,再执行重启。
修改UPDATE_INSTALLED状态的处理逻辑
case codePush.SyncStatus.UPDATE_INSTALLED: { rootStore.userStorage.setUpdateStatus(status); setStatus(status); rootStore.userStorage.setIsShowProgressBar(false); rootStore.userStorage.setIsShowUpdateProgress(false); // 显示与启动屏一致的过渡组件 rootStore.userStorage.setShowBootsplashOverlay(true); // 延迟200ms确保组件渲染完成后再重启 setTimeout(() => { codePush.allowRestart(); codePush.restartApp(true); }, 200); break; }
在根组件中添加过渡组件
在应用根组件中,根据showBootsplashOverlay状态渲染全屏过渡界面:
// 根组件示例 if (rootStore.userStorage.showBootsplashOverlay) { return ( <View style={{ flex: 1, backgroundColor: '#你的启动屏背景色' }}> <Image source={require('./assets/bootsplash-logo.png')} // 替换为你的启动屏图片 style={{ flex: 1, resizeMode: 'contain' }} /> </View> ); }
2. 原生端优化启动屏配置
确保react-native-bootsplash在重启流程中能快速显示,避免空档:
Android端
修改MainActivity.kt,确保启动屏持续显示直到RN初始化完成:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 保留启动屏直到RN发送隐藏信号 SplashScreen.show(this, true) }
iOS端
修改AppDelegate.swift,确保启动屏配置在重启时生效:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // 初始化启动屏 RNBootSplash.initStoryboard("BootSplash", rootView: rootView) return true }
3. 调整CodePush重启策略
避免使用restartApp(true)强制立即重启,改为让用户手动触发重启(比如显示"更新完成,点击重启"按钮),此时用户可以看到过渡界面,不会感知白屏。如果必须自动重启,上面的过渡组件方案是最优解。
内容的提问来源于stack exchange,提问作者Alexandr Nikitin
相关产品推荐
相关产品推荐

