dart
import 'dart:async';
import 'package:flutter_vlc_player/flutter_vlc_player.dart';
import 'package:flutter/material.dart';
class GlobalVlcController extends ChangeNotifier {
//设置单例
/*static final GlobalVlcController _instance = GlobalVlcController._internal();
factory GlobalVlcController() => _instance;
GlobalVlcController._internal();*/
late VlcPlayerController _controller;
String? _currentUrl;
bool _isInitialized = false;
VlcPlayerController get controller => _controller;
bool get isInitialized => _isInitialized;
VoidCallback? _onInitListener;
bool isSetLoop = false;
//初始化控制器
Future<void> initialize({String? url}) async {
print('视频播放器初始化==========$_isInitialized');
if (_isInitialized) {
if (_currentUrl != url && url != null && url.isNotEmpty) {
await setDataSource(url);
}
return;
}
_doInit(url);
}
/*
* 这个方法自带初始化无需再调用initialized()
* 控制器虽然初始化完成但是元数据还未解析完成。
* _controller.value.isInitialized为true,但是获取视频宽高时可能获取不到。
* 可以使用轮询Timer.periodic()去获取,获取到后取消轮询[可看获取 宽、高示例]
* */
_doInit(String? url){
_controller = VlcPlayerController.network(
url?? '',
autoPlay: false,
options: VlcPlayerOptions(
advanced: VlcAdvancedOptions([
VlcAdvancedOptions.networkCaching(200),
]),
rtp: VlcRtpOptions([
VlcRtpOptions.rtpOverRtsp(true),
]),
http: VlcHttpOptions([
VlcHttpOptions.httpReconnect(true),
]),
)
);
_currentUrl = url;
_isInitialized = true;
notifyListeners();
}
//设置播放资源
Future<void> setDataSource(String url) async {
if (_currentUrl == url) return;
_currentUrl = url;
await _controller.stop();
await _controller.setMediaFromNetwork(url);
notifyListeners();
}
//播放
Future<void> play() async {
await _controller.play();
}
//暂停
Future<void> pause() async {
await _controller.pause();
}
//初始化监听-只会调用一次
Future<void> addOnInitListener(VoidCallback listener) async {
if (_isInitialized) {
_onInitListener = listener;
_controller.addOnInitListener(_onInitListener!);
}
}
//添加监听
addListener(VoidCallback listener) {
if(_isInitialized){
_controller.addListener(listener);
}
}
//移除监听
removeListener(VoidCallback listener){
if(_isInitialized){
_controller.removeListener(listener);
}
}
//设置循环播放-vlcPlayer设置循环播放失效,以这种方式循环播放
addLoopListener(){
if(_isInitialized){
_controller.addListener(loopListener);
}
}
loopListener(){
if (_controller.value.playingState == PlayingState.ended) {
_controller.stop().then((_){
_controller.setVolume(0);
_controller.play();
isSetLoop = true;
notifyListeners();
print('isSetLoop===== $isSetLoop');
});
}
}
//销毁控制器
Future<void> disposeController() async {
print('=播放器销毁释放===');
try {
if (_isInitialized && controller.value.isInitialized) {
if(_onInitListener != null){
_controller.removeOnInitListener(_onInitListener!);
}
if(isSetLoop == true){
_controller.removeListener(loopListener);
isSetLoop = false;
}
if(_controller.value.isInitialized == true){
/*if(_controller.value.isPlaying){
_controller.pause();
}*/
await _controller.stop();
await _controller.dispose().then((_){
_isInitialized = false;
_currentUrl = null;
notifyListeners();
});
}
}
}catch(e){
print('销毁出错:${e}');
}
}
/*
* 获取宽、高示例
* */
getVideoSizeInfo() async {
if (_isInitialized && _controller.value.isInitialized) {
int _attempt = 0;
Timer.periodic(Duration(milliseconds: 300), (timer) {
final _size = _controller.value.size;
if (_size.width > 0 && _size.height > 0) {
timer.cancel(); // 宽高有值了,停止轮询
print('width===== ${_size.width}');
print('height===== ${_size.height}');
}else if(_attempt>= 200){//1分钟后还未获取到停止轮询
timer.cancel();
}
});
}
}
}
引用
dart
GlobalVlcController _glc = GlobalVlcController();
///....对_glc的一系列引用