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

Flutter使用youtube_player_flutter遇LateInitializationError问题求助

问题根源分析
  1. 全局声明的late YoutubePlayerController _youtubePlayerController在build方法执行时,YoutubePlayerBuilder的player参数会直接访问这个未初始化的变量,触发LateInitializationError。
  2. 错误地将同一个全局控制器赋值给所有列表项的YoutubePlayer,导致视频逻辑混乱,且控制器初始化时机滞后于组件渲染。
  3. 生命周期方法拼写错误:deactive应为deactivate,dipose应为dispose,导致控制器无法被正确暂停/释放。
解决方案

1. 移除全局控制器,为每个列表项单独创建控制器

每个视频项需要独立的控制器,避免全局变量的初始化冲突。

2. 修复生命周期方法拼写

确保Flutter能正确调用组件的生命周期钩子,管理控制器资源。

3. 调整YoutubePlayerBuilder的使用

无需全局包裹YoutubePlayerBuilder,每个列表项内部的YoutubePlayer可独立运行(如需全局播放器覆盖层,可将Builder移到Scaffold层级)。

修改后的完整代码
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:mahuva_azadari/Models/LinkModel.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
import 'package:http/http.dart' as http;
import '../Models/Hexa color.dart';

class LiveProgram extends StatefulWidget {
  const LiveProgram({Key? key}) : super(key: key);

  @override
  State<LiveProgram> createState() => _LiveProgramState();
}

class _LiveProgramState extends State<LiveProgram> {
  // 移除全局控制器变量

  Future<LinkModel> getAllLinks() async {
    var url = "https://aeliya.000webhostapp.com/MajlisLinks.php";
    var response = await http.get(Uri.parse(url));
    var jsondata = jsonDecode(response.body.toString());

    if (response.statusCode == 200) {
      return LinkModel.fromJson(jsondata);
    } else {
      return LinkModel.fromJson(jsondata);
    }
  }

  @override
  void deactivate() {
    // 全局无控制器,此处可移除,或改为遍历列表项控制器进行暂停(需额外存储控制器列表)
    super.deactivate();
    print("deactivate");
  }

  @override
  void dispose() {
    // 全局无控制器,此处可移除,或改为遍历列表项控制器进行释放(需额外存储控制器列表)
    super.dispose();
    print("dispose");
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: const Text(
            "Live Program",
            style: TextStyle(
              fontWeight: FontWeight.bold,
              fontSize: 25,
            ),
          ),
          centerTitle: true,
          backgroundColor: Color(hexColors('006064')),
        ),
        body: FutureBuilder<LinkModel>(
          future: getAllLinks(),
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return ListView.builder(
                itemCount: snapshot.data!.data!.length,
                itemBuilder: (context, index) {
                  var allItem = snapshot.data!.data![index];
                  // 为每个列表项单独创建控制器
                  final videoId = YoutubePlayer.convertUrlToId(allItem.link!);
                  if (videoId == null) {
                    return const Padding(
                      padding: EdgeInsets.all(8.0),
                      child: Text("无效的YouTube链接"),
                    );
                  }
                  final controller = YoutubePlayerController(
                    initialVideoId: videoId,
                    flags: const YoutubePlayerFlags(
                      autoPlay: false,
                    ),
                  )..addListener(() {
                      if (mounted) setState(() {});
                    });

                  return Container(
                    margin: const EdgeInsets.all(8),
                    child: Card(
                      color: Color(hexColors("00BCD4")),
                      elevation: 6,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(10.0),
                      ),
                      child: Column(
                        children: [
                          YoutubePlayer(
                            controller: controller,
                            showVideoProgressIndicator: true,
                          ),
                          const SizedBox(height: 10),
                          Text(
                            controller.metadata.title.isEmpty
                                ? 'Loading Title.....'
                                : "Title: ${controller.metadata.title}",
                            textAlign: TextAlign.left,
                            style: const TextStyle(
                              color: Colors.white,
                              fontSize: 15,
                              fontWeight: FontWeight.w700,
                              fontStyle: FontStyle.italic,
                            ),
                          ),
                          Text("City : ${allItem.city!}"),
                          Text("Post Date : ${allItem.postDateTime!}")
                        ],
                      ),
                    ),
                  );
                },
              );
            } else {
              return const Center(child: CircularProgressIndicator());
            }
          },
        ),
      ),
    );
  }
}

额外优化建议

如果需要统一管理所有列表项的控制器(比如页面销毁时统一释放),可以在状态类中添加一个List<YoutubePlayerController>变量,在创建控制器时加入列表,然后在dispose方法中遍历释放:

List<YoutubePlayerController> _controllers = [];

// 创建控制器时
final controller = YoutubePlayerController(...);
_controllers.add(controller);

// dispose方法中
@override
void dispose() {
  for(var ctrl in _controllers){
    ctrl.dispose();
  }
  super.dispose();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 07:10:28