Flutter页面切换时Chewie视频重复加载问题及解决方案咨询
解决方案
1. 修复 FutureBuilder 重复请求问题
当前代码中,FutureBuilder 的 future 参数直接调用 fetchPost(),导致每次页面重建都会重新发起请求,进而触发 ListView 重建,视频播放器被销毁重建。
修改方式:在 state 中存储 Future 实例,仅在 initState 中初始化一次:
// 在 _ThemeDayState 中添加 late Future<List<dynamic>> _dataFuture; @override void initState() { super.initState(); _dataFuture = Future.wait([fetchPost(), currentUserUpdate.getUserData()]); } // 然后在 FutureBuilder 中使用: FutureBuilder( future: _dataFuture, // ... 其余代码不变 )
2. 实现视频本地缓存
使用 flutter_cache_manager 库缓存视频文件,避免重复下载。先添加依赖到 pubspec.yaml:
dependencies: flutter_cache_manager: ^3.3.1
修改 CachedVideoPlayer 使用缓存的视频文件路径:
import 'package:flutter_cache_manager/flutter_cache_manager.dart'; class CachedVideoPlayer extends StatefulWidget { final String videoUrl; const CachedVideoPlayer({required this.videoUrl, Key? key}) : super(key: key); @override _CachedVideoPlayerState createState() => _CachedVideoPlayerState(); } class _CachedVideoPlayerState extends State<CachedVideoPlayer> { late VideoPlayerController _videoPlayerController; late ChewieController _chewieController; bool _isVideoLoading = true; @override void initState() { super.initState(); _initializeVideo(); } Future<void> _initializeVideo() async { // 获取缓存的视频文件 final file = await DefaultCacheManager().getSingleFile(widget.videoUrl); _videoPlayerController = VideoPlayerController.file(file); _chewieController = ChewieController( videoPlayerController: _videoPlayerController, aspectRatio: 12 / 16, autoPlay: false, looping: false, allowFullScreen: true, showControls: false, ); _videoPlayerController.addListener(() { if (_videoPlayerController.value.hasError) { print('Ошибка загрузки видео: ${_videoPlayerController.value.errorDescription}'); } }); await _videoPlayerController.initialize(); setState(() { _isVideoLoading = false; }); } @override void dispose() { _videoPlayerController.dispose(); _chewieController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Stack( children: [ if (!_isVideoLoading) Chewie(controller: _chewieController), if (_isVideoLoading) const Center( child: SizedBox( width: 15, height: 15, child: CircularProgressIndicator(), ), ), ], ); } }
3. 稳定列表项的 Key,避免不必要的重建
在 ListView.builder 的 itemBuilder 中,使用基于 post ID 的稳定 Key,确保相同的 post 复用之前的 widget 实例:
return GestureDetector( key: Key('post_${post.id}'), // 添加稳定Key onTap: () { // ... 跳转代码不变 }, child: ListTile( // ... 其余代码不变 ), );
4. 保留视频播放器状态
为 CachedVideoPlayer 混入 AutomaticKeepAliveClientMixin,确保页面切换或列表滚动时视频状态不丢失:
class _CachedVideoPlayerState extends State<CachedVideoPlayer> with AutomaticKeepAliveClientMixin<CachedVideoPlayer> { @override bool get wantKeepAlive => true; // ... 其余代码不变 }
总结
通过以上修改:
- 避免了重复请求导致的页面频繁重建
- 视频文件本地缓存,彻底消除重复下载
- 稳定的 widget Key 和 KeepAlive 机制,确保视频播放器状态被持久保留
内容的提问来源于stack exchange,提问作者Миша Тирский
相关产品推荐
相关产品推荐

