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

如何通过TextFormField输入链接动态展示视频?

问题

我们有TextFormField和ElevatedButton组件,要求用户输入MP4格式的视频URL,点击按钮后在组件下方展示从该URL爬取的视频。打算用video_player包,但示例代码要求在initState(或GetX的onInit)中设置初始URL,请问怎么实现URL动态化,且仅在输入URL后才展示视频?

现有代码

控制器代码

class CyberDropController extends GetxController with StateMixin<List> {
  final dataCyberDrop = DataCyberDrop();
  late VideoPlayerController videoController;
  var url = ''.obs;

  @override
  void onInit() {
    super.onInit();
    playVideo(url.value);
    change(null, status: RxStatus.empty());
  }

  Future<void> playVideo(String url) async {
    videoController = VideoPlayerController.network(url);
    await videoController.initialize();
    await videoController.setLooping(true);
    await videoController.play();
    update();
  }

  void fetch({String? link}) async {
    change(null, status: RxStatus.loading());
    try {
      var data = await dataCyberDrop.scraperCyberDrop(link: link);
      change(data, status: RxStatus.success());
    } catch (e) {
      change(null, status: RxStatus.error(e.toString()));
    }
  }
}

视图代码

controller.obx(
  (state) => Column(
    children: state!
        .map(
          (e) => e!.toString().contains('.mp4')
              ? AspectRatio(
                  aspectRatio: controller
                      .videoController.value.aspectRatio,
                  child: VideoPlayer(controller.videoController),
                )
              : Image.network(e),
        )
        .toList(),
)
解决方案

1. 修复控制器初始化逻辑,避免空URL报错

原代码在onInit里直接调用playVideo传入空字符串,会导致VideoPlayerController初始化失败。我们需要:

  • 把videoController改为可空类型,避免late变量未初始化的风险
  • 移除onInit中的playVideo调用,只在用户输入有效URL后再初始化控制器

修改后的控制器变量定义:

VideoPlayerController? videoController;

2. 优化playVideo方法,处理动态切换与资源释放

动态切换URL时,必须先释放旧的控制器,否则会造成内存泄漏。同时增加URL有效性判断:

Future<void> playVideo(String url) async {
  // 先释放旧的控制器
  if (videoController != null) {
    await videoController!.dispose();
  }

  if (url.isEmpty || !url.endsWith('.mp4')) {
    change(null, status: RxStatus.error('请输入有效的MP4视频链接'));
    return;
  }

  try {
    videoController = VideoPlayerController.network(url);
    await videoController!.initialize();
    await videoController!.setLooping(true);
    await videoController!.play();
    update(); // 更新视图
  } catch (e) {
    change(null, status: RxStatus.error('视频加载失败: ${e.toString()}'));
  }
}

3. 绑定输入框与按钮逻辑

在视图中添加TextFormField和ElevatedButton,将输入内容绑定到控制器的url变量,点击按钮时触发视频加载:

// 输入框部分
Obx(
  () => TextFormField(
    decoration: const InputDecoration(hintText: '输入MP4视频URL'),
    onChanged: (value) => controller.url.value = value,
    controller: TextEditingController(text: controller.url.value),
  ),
),

// 按钮部分
ElevatedButton(
  onPressed: () {
    // 如果需要先爬取链接,调用fetch后再处理返回的MP4地址
    // controller.fetch(link: controller.url.value);
    // 直接加载输入的URL则调用playVideo
    controller.playVideo(controller.url.value);
  },
  child: const Text('加载视频'),
),

4. 条件渲染视频组件

只有当videoController存在且已初始化时,才展示视频播放器,避免空指针错误:

controller.obx(
  (state) => Column(
    children: state!
        .map(
          (e) {
            if (e!.toString().contains('.mp4')) {
              // 若为爬取到的MP4链接,可在fetch成功后调用playVideo加载对应链接
              // 单视频场景下直接判断当前videoController状态
              return controller.videoController != null && controller.videoController!.value.isInitialized
                  ? AspectRatio(
                      aspectRatio: controller.videoController!.value.aspectRatio,
                      child: VideoPlayer(controller.videoController!),
                    )
                  : const SizedBox.shrink();
            } else {
              return Image.network(e);
            }
          },
        )
        .toList(),
  ),
),

5. 资源清理(可选但重要)

在控制器的onClose方法中释放视频控制器,避免内存泄漏:

@override
void onClose() {
  videoController?.dispose();
  super.onClose();
}

多视频场景补充(如果爬取返回多个MP4链接)

如果fetch方法返回的列表中有多个MP4链接,需要为每个视频创建独立的控制器。可以把videoController改为Map<String, VideoPlayerController?>来存储每个链接对应的控制器,在遍历state时初始化对应链接的控制器。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 21:55:19