我正在使用抖动video_player
包播放视频列表。
List sourceList;
sourceList = [
{
"size": 69742504,
"name": "lucky-roulette.mp4",
"mimetype": "video/mp4",
},
{
"size": 69742504,
"name": "BigBuckBunny.mp4",
"mimetype": "video/mp4",
}
];
我已经检出this issue,并对其进行了一些自定义代码。
void play() {
log.fine("Now playing: $_nowPlayingUrl");
_adController = VideoPlayerController.network(_nowPlayingUrl);
_adController.initialize().then((_) => setState(() {}));
_adController.play();
_adController.addListener(checkIfVideoFinished);
}
void checkIfVideoFinished() {
if (_adController == null ||
_adController.value == null ||
_adController.value.position == null ||
_adController.value.duration == null) return;
if (_adController.value.position.inSeconds ==
_adController.value.duration.inSeconds) {
_adController.removeListener(checkIfVideoFinished);
_adController.dispose();
// Change _nowPlayingIndex
setState(() {
_nowPlayingIndex = (_nowPlayingIndex + 1) % _totalIndex;
});
play();
}
}
但是使用此代码段将发出异常Another exception was thrown: A VideoPlayerController was used after being disposed.
是否有更好的方法在Flutter中播放和循环播放视频列表?
答案 0 :(得分:1)
您必须在Override dispose方法中调用视频控制器dispose方法。 removevideo时无需调用dispose方法。
答案 1 :(得分:0)
我还认为在处置Widget之前不调用dispose
是可以的。
就我而言,我暂停了每个视频文件。我将FutureBuilder与VideoPlayerController一起使用。
依存关系video_player: ^0.10.1
chewie: ^0.9.7
码
VideoPlayerController _controller;
ChewieController _chewieController; // custom ui
Future<void> _initializeVideoPlayerFuture;
var _clips = List<PoseClip>(); // video list
int _playingIndex = -1;
bool _disposed = false;
var _isPlaying = false;
var _isEndPlaying = false;
@override
void dispose() {
_disposed = true;
// By assigning Future is null,
// prevent the video controller is using in widget before disposing that.
_initializeVideoPlayerFuture = null;
// In my case, sound is playing though controller was disposed.
_controller?.pause()?.then((_){
// dispose VideoPlayerController.
_controller?.dispose();
});
super.dispose();
}
Future<bool> _clearPrevious() async {
await _controller?.pause();
_controller?.removeListener(_controllerListener);
return true;
}
Future<void> _startPlay(int index) async {
print("play ---------> $index");
setState(() {
_initializeVideoPlayerFuture = null;
});
Future.delayed(const Duration(milliseconds: 200), () {
_clearPrevious().then((_){
_initializePlay(index);
});
});
}
Future<void> _initializePlay(int index) async {
final file = await _localStorage.localFile(_clips[index].filePath());
print("file.exists: ${file.existsSync()}");
print("file.path: ${file.path}");
_controller = VideoPlayerController.file(file);
_controller.addListener(_controllerListener);
_chewieController = ChewieController(videoPlayerController: _controller);
_initializeVideoPlayerFuture = _controller.initialize();
setState(() {
_playingIndex = index;
});
}
// tracking status
Future<void> _controllerListener() async {
if (_controller == null || _disposed) {
return;
}
if (!_controller.value.initialized) {
return;
}
final position = await _controller.position;
final duration = _controller.value.duration;
final isPlaying = position.inMilliseconds < duration.inMilliseconds;
final isEndPlaying = position.inMilliseconds > 0 && position.inSeconds == duration.inSeconds;
if (_isPlaying != isPlaying || _isEndPlaying != isEndPlaying) {
_isPlaying = isPlaying;
_isEndPlaying = isEndPlaying;
print("$_playingIndex -----> isPlaying=$isPlaying / isCompletePlaying=$isEndPlaying");
if (isEndPlaying) {
final isComplete = _playingIndex == _clips.length - 1;
if (isComplete) {
print("played all!!");
} else {
_startPlay(_playingIndex + 1);
}
}
}
}
// play view area
Widget _playView() {
// FutureBuilder to display a loading spinner until finishes initializing
return FutureBuilder(
future: _initializeVideoPlayerFuture,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
_chewieController.play();
return AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: Chewie(controller: _chewieController),
);
} else {
return SizedBox(
height: 300,
child: Center(child: CircularProgressIndicator()),
);
}
},
);
}