[英]Flutter video_player dispose
我正在使用带有video_player
的provider
来管理 state。
VideoProvider 有:
videoPlayerController = VideoPlayerController.network(...);
当用户切换到新视频(同一屏幕)时,我经常更改它。 如果我直接将 new VideoPlayerController.network(...)
分配给videoPlayerController
,旧视频仍会播放并且您可以听到声音。 解决方法是使用videoPlayerController.pause()
然后分配一个新的VideoPlayerCOntroller.network
。
以前的视频是否正在被 GC 处理? 这有什么性能问题吗? 我想在切换到新视频之前摆脱以前的视频和使用的资源。 我不能在切换之前使用videoPlayerController.dispose()
,因为它会导致错误。
当您调用dispose
时,您的 controller 仍在被VideoPlayer小部件使用。 首先,您需要确保不再使用它(将 state 中的 controller 设置为 null)并在调用 dispose 之后。
我不确定你的 state 通过 Provider 管理,但我会给你一个例子,如何使用常规 State 做到这一点。
VideoPlayerController _controller;
void _initController(String link) {
_controller = VideoPlayerController.network(link)
..initialize().then((_) {
setState(() {});
});
}
Future<void> _onControllerChange(String link) async {
if (_controller == null) {
// If there was no controller, just create a new one
_initController(link);
} else {
// If there was a controller, we need to dispose of the old one first
final oldController = _controller;
// Registering a callback for the end of next frame
// to dispose of an old controller
// (which won't be used anymore after calling setState)
WidgetsBinding.instance.addPostFrameCallback((_) async {
await oldController.dispose();
// Initing new controller
_initController(link);
});
// Making sure that controller is not used by setting it to null
setState(() {
_controller = null;
});
}
}
我知道它很晚,但这将帮助其他有同样问题的人。
我有同样的问题,当用户从列表中选择新视频时,我想更改视频,经过大量研究,我终于自己创建了一个解决方案。
按照以下步骤,您可以在同一屏幕上的视频播放器中播放视频
VideoPlayer
的StatefulWidget
class 并在init
方法中初始化 videoPlayerController。 假设您创建了一个名为 MyVideoPlayer 的 StatefulWidget class 然后在构造函数中接受两个变量,即 i> String videoLink ii> UniqueKey()注意- 您必须将 UniqueKey() 传递给此 class 的上级,例如,
class MyVideoPlayer extends StatefulWidget {
final String videoLink;
final UniqueKey newKey;
MyVideoPlayer(this.videoLink, this.newKey): super(key: newKey); // passing Unique key to dispose old class instance and create new with new data
@override
_MyVideoPlayerState createState() => _MyVideoPlayerState();
} ...
将您正在播放视频的主 dart 文件的VideoPlayer
实例替换为您之前创建的 class 即MyVideoPlayer
并传递 videoLink 和UniqueKey()
。
现在,每当您想更改视频时,只需更新主 dart 文件的setState(() {})
内的 videoLink,然后通过完全处理旧的 VideoPlayer 实例创建一个新的 VideoPlayer 实例。
注意 - 这里的主要工作是由 UniqueKey() 完成的,通过传递 UniqueKey() 你说 flutter 来创建这个特定 class 的新唯一实例;
你可以使用它:
@override
void dispose() {
if (_controller.value.isPlaying) _controller.pause();
_controller.removeListener(_videoListener);
_controller = null;
super.dispose();
}
我知道是以后,但我想我找到了解决这个问题的一种方法。
1.创建initPlayer()
(我使用Provider
创建)
void initPlayer( {pause = false, update = false, updateUrl = ""} ) async {
var isPlaying = false;
if (controller == null) {
controller = VideoPlayerController.file(File(url))..addListener(() {
isPlaying = true;
notifyListeners();
})..initialize().then((value) => notifyListeners());
controller.play();
} else {
print ("Controller is playing...");
if (pause) {
if (controller.value.isPlaying) {
controller.pause();
} else {
controller.play();
}
}
if (update && updateUrl != "") {
final oldController = controller;
await oldController.dispose();
controller = VideoPlayerController.file(File(updateUrl))..addListener(() {
isPlaying = true;
notifyListeners();
})..initialize().then((value) => notifyListeners());
controller.play();
}
}
}
在小部件中添加Actions
( start
、 pause
change
)。
child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ FlatButton( child: Text("Play Video"), color: Colors.red, onPressed: () { musicPlayerProvider.initPlayer(); }, ), FlatButton( child: Text("Stop Video"), color: Colors.pink, onPressed: () { musicPlayerProvider.initPlayer(pause: true); }, ), FlatButton( child: Text("Change Video"), color: Colors.yellow, onPressed: () { musicPlayerProvider.initPlayer(update: true,updateUrl: "url"); }, ), ],),
目前这works
,但您当然可以进行更改。
稍后我们需要使用addListener
方法检查video
何时finished
(我猜)。
感谢此链接中的某人,这解决了我的问题
void dispose() {
_controller.pause();
_controller?.dispose();
//ignore below
audioPlayer.stop();
audioPlayer?.dispose();
super.dispose();
}
我正在制作 Instagram 网格视图。 每次我选择一个新文件时,我都应该更新我的缩略图。 但是我的有状态小部件无法识别更新。 dispose 方法没有启动。
最后我想到了这个。 希望这会对某人有所帮助。
class _SelectedVideo extends StatefulWidget {
const _SelectedVideo({
Key? key,
required this.file,
}) : super(key: key);
final File file;
@override
State<_SelectedVideo> createState() => _SelectedVideoState();
}
class _SelectedVideoState extends State<_SelectedVideo> {
VideoPlayerController? _controller;
void _initVideoPlayer(File file) async {
_controller = VideoPlayerController.file(
file,
);
await _controller!.initialize();
_controller!.setVolume(0);
_controller!.play();
setState(() {});
}
@override
void initState() {
super.initState();
_initVideoPlayer(widget.file);
}
@override
void didUpdateWidget(covariant _SelectedVideo oldWidget) {
// I'm disposing controller all the time when widget updates
_controller?.dispose();
_initVideoPlayer(widget.file);
super.didUpdateWidget(oldWidget);
}
@override
void dispose() {
_controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (_controller == null) return Container();
return Container(
color: Colors.black,
height: 375,
width: double.infinity,
child: FittedBox(
fit: BoxFit.cover,
clipBehavior: Clip.hardEdge,
child: SizedBox(
width: _controller!.value.size.width,
height: _controller!.value.size.height,
child: AspectRatio(
aspectRatio: _controller!.value.aspectRatio,
child: VideoPlayer(_controller!),
),
),
),
);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.