使用Chewie播放视频时出现LateInitializationError的解决咨询
修复Flutter中Chewie组件的LateInitializationError错误
问题场景
通过API获取视频链接后,使用Chewie组件播放视频时触发LateInitializationError,原代码如下:
import 'dart:convert'; import 'package:chewie/chewie.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; import 'package:video_box/video_box.dart'; class Player extends StatefulWidget { final int id; const Player({Key? key,required this.id}) : super(key: key); @override State<Player> createState() => _PlayerState(); } class _PlayerState extends State<Player> { bool loadedData = true; late ChewieController _chewieController; @override void initState() { super.initState(); loadData(); } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: loadedData? const Center( child: RefreshProgressIndicator(), ): Chewie(controller: _chewieController), ); } void loadData() async{ var url = Uri.https('my api', {'q': '{http}'}); var response = await get(url); var link = json.decode(utf8.decode(response.bodyBytes)); String videoLink = link['videoLink']; setState(() { String link = videoLink; late final VideoPlayerController _videoPlayerController = VideoPlayerController.networkUrl( Uri.parse(link) ); late final ChewieController _chewieController = ChewieController( videoPlayerController: _videoPlayerController, aspectRatio: MediaQuery.of(context).size.width / MediaQuery.of(context).size.height ); _videoPlayerController.initialize(); loadedData = false; }); } }
错误原因
- 类级别声明的
_chewieController标记了late,但实际在setState里重新声明了同名局部变量,导致类的_chewieController从未被赋值,当loadedData变为false时,Build方法访问未初始化的类变量触发错误。 _videoPlayerController.initialize()是异步操作,未等待完成就更新loadedData,可能导致视频未初始化完成就渲染播放器。- 未在
dispose中销毁控制器,会引发内存泄漏。 - 未处理API请求和解析的异常情况,容易崩溃。
- 导入了错误的库:
video_box不是Chewie依赖的基础库,应该用video_player。
修复方案
步骤1:声明类级控制器变量
把_videoPlayerController和_chewieController都声明为类级变量,方便后续管理:
late VideoPlayerController _videoPlayerController; late ChewieController _chewieController;
步骤2:正确初始化控制器
在loadData中直接赋值类变量,等待视频初始化完成后再更新状态,同时增加异常处理:
void loadData() async { try { var url = Uri.https('my api', {'q': '{http}'}); var response = await get(url); // 检查请求是否成功 if (response.statusCode != 200) { throw Exception('请求失败,状态码:${response.statusCode}'); } var link = json.decode(utf8.decode(response.bodyBytes)); String videoLink = link['videoLink']; _videoPlayerController = VideoPlayerController.networkUrl(Uri.parse(videoLink)); // 等待视频初始化完成 await _videoPlayerController.initialize(); setState(() { _chewieController = ChewieController( videoPlayerController: _videoPlayerController, aspectRatio: MediaQuery.of(context).size.width / MediaQuery.of(context).size.height, // 可添加更多配置 autoPlay: false, looping: false, ); loadedData = false; }); } catch (e) { setState(() { loadedData = false; // 异常提示 ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('加载失败:$e'))); }); } }
步骤3:销毁控制器释放资源
在dispose方法中销毁两个控制器,避免内存泄漏:
@override void dispose() { _videoPlayerController.dispose(); _chewieController.dispose(); super.dispose(); }
步骤4:优化Build方法的安全判断
在loadedData为false时,额外判断控制器是否已初始化,增加安全性:
@override Widget build(BuildContext context) { return Scaffold( body: loadedData ? const Center(child: RefreshProgressIndicator()) : (_chewieController.videoPlayerController.value.isInitialized ? Chewie(controller: _chewieController) : const Center(child: Text('视频初始化中'))), ); }
完整修复代码
import 'dart:convert'; import 'package:chewie/chewie.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; import 'package:video_player/video_player.dart'; // 替换为正确的依赖库 class Player extends StatefulWidget { final int id; const Player({Key? key, required this.id}) : super(key: key); @override State<Player> createState() => _PlayerState(); } class _PlayerState extends State<Player> { bool loadedData = true; late VideoPlayerController _videoPlayerController; late ChewieController _chewieController; @override void initState() { super.initState(); loadData(); } @override void dispose() { _videoPlayerController.dispose(); _chewieController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: loadedData ? const Center(child: RefreshProgressIndicator()) : (_chewieController.videoPlayerController.value.isInitialized ? Chewie(controller: _chewieController) : const Center(child: Text('视频初始化中'))), ); } void loadData() async { try { var url = Uri.https('my api', {'q': '{http}'}); var response = await get(url); if (response.statusCode != 200) { throw Exception('请求失败,状态码:${response.statusCode}'); } var link = json.decode(utf8.decode(response.bodyBytes)); String videoLink = link['videoLink']; _videoPlayerController = VideoPlayerController.networkUrl(Uri.parse(videoLink)); await _videoPlayerController.initialize(); setState(() { _chewieController = ChewieController( videoPlayerController: _videoPlayerController, aspectRatio: MediaQuery.of(context).size.width / MediaQuery.of(context).size.height, autoPlay: false, looping: false, ); loadedData = false; }); } catch (e) { setState(() { loadedData = false; ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('加载失败:$e'))); }); } } }
内容的提问来源于stack exchange,提问作者user17657114
相关产品推荐
相关产品推荐

