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();}});}}}
引用
GlobalVlcController _glc = GlobalVlcController();
///....對_glc的一系列引用