You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 08:04:53