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

如何使用GetX为Flutter视频播放器动态分配URL并更新UI

如何使用GetX为Flutter视频播放器动态分配URL并更新UI

看起来你遇到了两个头疼的问题——视频播放器得靠热重载才显示,还有没法从TopicView页面动态把视频URL传给控制器。别担心,咱们一步步把这些问题理顺,同时优化下代码结构。

第一步:重构VPlayerController,支持动态URL和自动UI更新

原来的控制器有几个小问题:硬编码了URL、chewieController不是响应式变量、初始化逻辑还重复了。咱们改成响应式的,再加个动态设置URL的方法:

class VPlayerController extends GetxController {
  late VideoPlayerController videoPlayerController;
  // 改成响应式变量,变化时自动触发UI更新
  final Rx<ChewieController?> chewieController = Rx<ChewieController?>(null);
  // 记录当前URL,避免重复初始化相同视频
  String? currentUrl;

  @override
  void onInit() {
    super.onInit();
  }

  // 新增:动态设置视频URL的核心方法
  Future<void> setVideoUrl(String url) async {
    // 相同URL直接返回,省得重复折腾
    if (currentUrl == url) return;
    currentUrl = url;

    // 先释放旧资源,防止内存泄漏
    if (videoPlayerController.value.isInitialized) {
      await videoPlayerController.dispose();
    }
    chewieController.value?.dispose();

    try {
      // 初始化新的视频控制器
      videoPlayerController = VideoPlayerController.network(url);
      await videoPlayerController.initialize();

      // 创建Chewie控制器并赋值给响应式变量
      chewieController.value = ChewieController(
        videoPlayerController: videoPlayerController,
        autoPlay: false,
        looping: true,
        showControls: true,
        errorBuilder: (context, errorMessage) {
          return Center(child: Text(errorMessage));
        },
        autoInitialize: true,
        materialProgressColors: ChewieProgressColors(
          bufferedColor: primary.withOpacity(0.5),
          backgroundColor: primary.withOpacity(0.5),
          handleColor: primary,
          playedColor: primary,
        ),
        cupertinoProgressColors: ChewieProgressColors(),
      );
    } catch (e) {
      Fluttertoast.showToast(msg: e.toString());
      // 出错时清空控制器,避免UI卡住
      chewieController.value = null;
    }
  }

  @override
  void onClose() {
    videoPlayerController.dispose();
    chewieController.value?.dispose();
    super.onClose();
  }
}

改动说明:

  • 把chewieController改成Rx响应式变量,不用手动调用update(),UI会自动跟着变化
  • 移除了重复的初始化逻辑,换成专门的setVideoUrl方法,处理旧资源释放和新视频初始化
  • 加了currentUrl判断,避免重复加载相同视频浪费资源
  • 错误处理更稳妥,出错时清空控制器,防止UI显示异常

第二步:修改TopicView页面,传递URL并自动监听状态

原来的页面用GetBuilder,还没给控制器传URL,导致控制器不知道要播啥。咱们换成Obx监听响应式变量,同时在页面初始化时把URL传过去:

class TopicView extends StatelessWidget {
  final String? url;
  // 提前初始化控制器,整个页面生命周期只实例化一次
  final VPlayerController _controller = Get.put(VPlayerController());

  const TopicView({super.key, this.url});

  @override
  Widget build(BuildContext context) {
    // 页面构建完成后再传URL,避免上下文问题
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (url != null) {
        _controller.setVideoUrl(url!);
      }
    });

    return Scaffold(
      appBar: AppBar(title: Text(widget.courseId)), // 注意这里的courseId要确保存在哦
      body: SizedBox(
        width: ScreenManager.getWidth(context),
        height: ScreenManager.getHeight(context),
        child: Padding(
          padding: const EdgeInsets.all(AppPadding.p16),
          child: Column(
            children: [
              Expanded(
                child: Obx(() {
                  final chewieController = _controller.chewieController.value;
                  final isInitialized = chewieController?.videoPlayerController.value.isInitialized ?? false;
                  
                  if (chewieController != null && isInitialized) {
                    return Chewie(controller: chewieController);
                  } else if (url == null) {
                    return const Text('没有提供视频URL');
                  } else {
                    return const Text('视频加载中...');
                  }
                }),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

改动说明:

  • 用Get.put()提前初始化控制器,避免每次build都创建新实例
  • 用addPostFrameCallback确保页面渲染完成后再传URL,防止出现上下文错误
  • 替换GetBuilder为Obx,自动监听控制器的响应式变量变化,解决了热重载才显示的问题
  • 增加了不同状态的UI提示:加载中、无URL、视频加载完成,用户体验更好

为啥原来的代码需要热重载才显示?

原来的GetBuilder需要控制器手动调用update()才能触发UI刷新,但你之前的控制器初始化完成后没调用这个方法,所以UI压根不知道视频已经准备好啦。改成响应式变量后,Obx会自动盯着变量变化,视频一初始化好就更新UI,再也不用依赖热重载了。

备注:内容来源于stack exchange,提问作者Jackson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 13:17:51