Flutter桌面应用连续运行超24小时后停止页面切换求助
Flutter桌面应用长期运行后页面切换失效问题
我开发了一款简单的Flutter桌面应用,包含图片和视频播放器功能,通过页面导航逐个展示本地asset文件夹中的资源,遍历存储文件名及文件类型(isImage: true/false)的assetslist[]数组。应用运行24小时内一切正常,但超过24小时后会停止循环遍历列表,不再切换页面,屏幕冻结在当前内容上。
原本用来实现页面跳转的代码:
Future.delayed(Duration(seconds: 4), (){ Navigator.pushReplacement( context, PageTransition( duration: Duration(milliseconds: 100), type: PageTransitionType.fade, child:(assetslist[currentIndex].isImage)? DisplayImagePage(currentIndex:currentIndex): DartVclPlayer(currentIndex: currentIndex), ), ); });
所有资源、索引及文件类型均无问题,尝试改用MaterialPageRoute后,问题依然存在:
Future.delayed(Duration(seconds: 4), () { Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => (assetslist[currentIndex].isImage) ? DisplayImagePage(currentIndex: currentIndex) : DartVclPlayer( currentIndex: currentIndex, )); });
可能的原因及解决办法
1. 延迟任务累积导致队列阻塞
连续嵌套使用Future.delayed触发页面跳转,长期运行后会在Dart事件队列中堆积大量延迟任务,一旦出现未捕获的异步异常,就会导致整个队列停滞,页面切换中断。
解决办法:改用Timer.periodic定时调度
用周期定时器替代单次延迟任务,避免任务堆积,同时保证定时逻辑的稳定性:
late Timer _pageSwitchTimer; @override void initState() { super.initState(); // 初始化4秒周期的定时器 _pageSwitchTimer = Timer.periodic(Duration(seconds: 4), (timer) { // 更新索引,循环遍历列表 currentIndex = (currentIndex + 1) % assetslist.length; // 执行页面跳转 if (mounted) { Navigator.pushReplacement( context, PageTransition( duration: Duration(milliseconds: 100), type: PageTransitionType.fade, child: assetslist[currentIndex].isImage ? DisplayImagePage(currentIndex: currentIndex) : DartVclPlayer(currentIndex: currentIndex), ), ); } }); } @override void dispose() { _pageSwitchTimer.cancel(); // 页面销毁时务必取消定时器 super.dispose(); }
2. 资源未释放导致内存泄漏
长期运行中,图片缓存、视频播放器资源未正确释放,会导致内存占用持续升高,最终阻塞UI线程或异步任务执行。
解决办法:在页面销毁时清理资源
- 在
DisplayImagePage中清理图片缓存:
@override void dispose() { ImageCache.instance.clear(); ImageCache.instance.clearLiveImages(); super.dispose(); }
- 在
DartVclPlayer中停止并销毁播放器:
@override void dispose() { // 根据播放器实际API调用停止、销毁方法 player.stop(); player.dispose(); super.dispose(); }
3. 上下文失效导致导航失败
长期运行过程中,原页面的context可能因组件重建、状态变化等原因失效,导致Navigator.pushReplacement无法执行。
解决办法:增加挂载状态检查
在执行导航操作前,先判断组件是否处于挂载状态:
_timer = Timer.periodic(Duration(seconds: 4), (timer) { if (!mounted) { timer.cancel(); return; } // 执行索引更新和页面跳转逻辑 });
内容的提问来源于stack exchange,提问作者Yash Chaudhari
相关产品推荐
相关产品推荐

