React Native Realm Flexible Sync进度屏实现问题求助
解决Realm Flexible Sync实时进度监听与进度屏实现问题
问题根源分析
- 进度模式选择错误:你使用的
ProgressMode.ForCurrentlyOutstandingWork仅监听添加监听时已存在的待处理任务,但Flexible Sync中订阅建立后,服务器需要先计算待传输数据量,初始待处理任务为0,只有最终完成时才会触发回调。 - 监听时机不对:
useEffect依赖为空数组,可能realm.syncSession尚未初始化,导致监听未正确绑定。 - 主线程阻塞:大量数据同步操作默认在主线程执行,未完成时渲染主UI会引发卡顿。
解决方案
1. 修正进度监听逻辑
改用ProgressMode.ReportIndefinitely模式,确保持续监听所有后续下载任务;同时在订阅添加完成后再绑定进度监听,保证syncSession已就绪。
2. 实现进度屏控制
通过状态变量跟踪同步进度与完成状态,未完成时仅渲染轻量进度屏,避免主线程阻塞。
修正后的完整代码示例
enum ProgressDirection { Download = 'download', Upload = 'upload', } enum ProgressMode { ReportIndefinitely = 'reportIndefinitely', ForCurrentlyOutstandingWork = 'forCurrentlyOutstandingWork', } const AppSync = () => { const app = useApp(); const realm = useRealm(); const [syncProgress, setSyncProgress] = useState<number>(0); const [isSyncComplete, setIsSyncComplete] = useState<boolean>(false); useEffect(() => { // 先添加Flexible Sync订阅 const addSubscription = async () => { try { await realm.subscriptions.update((mutableSubs) => { // 替换为你的实际数据模型订阅逻辑 mutableSubs.add(realm.objects('YourDataModel')); }); // 订阅完成后绑定进度监听 setupProgressListener(); } catch (err) { console.error('订阅添加失败:', err); } }; // 配置进度监听 const setupProgressListener = () => { if (!realm.syncSession) return; const progressCallback = (transferred: number, transferable: number) => { if (transferable === 0) return; // 避免除以0错误 const percent = Math.round((transferred / transferable) * 100); setSyncProgress(percent); // 进度完成后停止监听并标记状态 if (percent >= 100) { setIsSyncComplete(true); realm.syncSession.removeProgressNotification(progressCallback); } }; realm.syncSession.addProgressNotification( ProgressDirection.Download, ProgressMode.ReportIndefinitely, progressCallback ); // 组件卸载时清理监听 return () => { realm.syncSession?.removeProgressNotification(progressCallback); }; }; addSubscription(); return () => { if (!realm.isClosed) realm.close(); }; }, [realm]); // 同步未完成时显示进度屏 if (!isSyncComplete) { return ( <div style={{display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100vh'}}> <p>数据同步中:{syncProgress}%</p> <div style={{width: '80%', height: 10, backgroundColor: '#eee', borderRadius: 5, overflow: 'hidden'}}> <div style={{width: `${syncProgress}%`, height: '100%', backgroundColor: '#4299e1'}}></div> </div> </div> ); } // 同步完成后渲染应用主体内容 return ( <div className="app-main-content"> {/* 你的应用核心UI */} </div> ); };
额外优化建议
- 监听连接状态:可以通过
realm.syncSession.state判断同步连接状态,处理网络断开等异常场景,给用户重试提示。 - 使用
useSubscription钩子:如果使用Realm React官方的useSubscription,可以更便捷地跟踪订阅状态,结合status字段辅助判断同步进度。 - 轻量进度屏:进度屏尽量使用简单DOM元素,避免复杂渲染逻辑,减少主线程负担。
内容的提问来源于stack exchange,提问作者Hardik Chavda
相关产品推荐
相关产品推荐

