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

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,提问作者Миша Тирский

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 14:32:31