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

如何在Flutter中实现适配PageView.builder的视频播放列表

PageView.builder 视频播放列表实现方案

现有代码存在的问题

  • 当前只初始化了单个VideoPlayerController,绑定固定的assets/vod_1.mp4,无法适配多视频列表场景
  • 翻页逻辑仅做了进度重置和播放,没有切换对应的视频资源,翻页后播放的还是原来的视频
  • 缺少控制器的释放逻辑,容易出现内存泄漏

完整实现步骤

1. 定义基础变量

先声明视频资源列表、当前播放下标、控制器相关变量:

// 按实际需求替换为你的本地/网络视频地址列表
final List<String> videoList = [
  'assets/vod_1.mp4',
  'assets/vod_2.mp4',
  'assets/vod_3.mp4',
];
late int currentIndex;
late VideoPlayerController _controller;

2. 重写初始化逻辑

封装通用的控制器初始化方法,修改原有的initState逻辑:

@override
void initState() {
  super.initState();
  currentIndex = 0;
  // 初始化首个视频的控制器
  _initController(videoList[currentIndex]);
}

// 控制器初始化公共方法,后续翻页可复用
void _initController(String videoPath) {
  _controller = VideoPlayerController.asset(videoPath)
    ..initialize().then((value) {
      _controller.play();
      _controller.setLooping(true);
      setState(() {});
    });
}

3. 修改PageView.builder逻辑

补充itemCount配置,修改翻页逻辑实现视频切换,补全itemBuilder返回播放组件:

return PageView.builder(
  // 配置总页数为视频列表长度
  itemCount: videoList.length,
  onPageChanged: (index) {
    if (index == currentIndex) return;
    // 先释放旧控制器避免内存泄漏
    _controller.dispose();
    // 更新当前播放下标
    currentIndex = index;
    // 初始化新视频的控制器
    _initController(videoList[currentIndex]);
    setState(() {});
  },
  itemBuilder: (context, index) {
    return _controller.value.isInitialized
        ? AspectRatio(
            aspectRatio: _controller.value.aspectRatio,
            child: VideoPlayer(_controller),
          )
        : const Center(child: CircularProgressIndicator());
  },
);

4. 补充页面销毁逻辑

页面退出时释放当前控制器,避免内存占用:

@override
void dispose() {
  _controller.dispose();
  super.dispose();
}

可选优化点

  • 可添加预加载逻辑,提前初始化下一页的视频控制器,减少翻页后的加载等待时间
  • 可加入滑动过程中暂停渲染的逻辑,降低滑动时的性能消耗
  • 如果是百级以上的长视频列表,可设置最大缓存控制器数量,避免同时占用过多内存

内容的提问来源于stack exchange,提问作者tabsen700

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 18:06:02