import 'dart:io'; import 'package:flutter/cupertino.dart'; import 'package:flutter_kinetra/kt_pages/kt_short_video/state.dart'; import 'package:get/get.dart'; import 'package:video_player/video_player.dart'; import '../../dio_cilent/kt_apis.dart'; import '../../dio_cilent/kt_request.dart'; import '../../kt_model/kt_video_detail_bean.dart'; import '../../kt_utils/kt_device_info_utils.dart'; import '../../kt_widgets/kt_status_widget.dart'; class VideoPlayLogic extends GetxController { final state = VideoPlayState(); late final PageController pageController; List controllers = []; int currentIndex = 0; bool _disposed = false; @override void onInit() { super.onInit(); pageController = PageController(initialPage: currentIndex); } @override void onReady() { super.onReady(); _disposed = false; state.shortPlayId = Get.arguments['shortPlayId']; state.videoId = Get.arguments['videoId'] ?? 0; state.imageUrl = Get.arguments['imageUrl'] ?? ''; state.activityId = Get.arguments['activityId']; state.isFromDiscover = Get.arguments['isFromDiscover'] ?? false; fetchData(); } @override void onClose() { _disposed = true; clearCacheCtrl(); super.onClose(); } clearCacheCtrl() { for (var controller in controllers) { controller?.pause(); controller?.dispose(); } controllers.clear(); } Future fetchData({bool toPage = true}) async { Map params = { 'short_play_id': state.shortPlayId, "video_id": state.videoId, }; if (state.activityId != null) { params['activity_id'] = state.activityId; } clearCacheCtrl(); try { // LottieLoading.show(Get.context!); ApiResponse res = await KtHttpClient().request( KtApis.getVideoDetails, method: HttpMethod.get, queryParameters: params, ); if (res.success) { state.loadStatus = KtLoadStatusType.loadSuccess; state.video = VideoDetailBean.fromJson(res.data); if (state.imageUrl == '') { state.imageUrl = state.video!.shortPlayInfo?.imageUrl ?? ''; } if (state.videoId == 0) { state.videoId = state.video?.videoInfo?.shortPlayVideoId ?? 0; } state.episodeList = state.video?.episodeList ?? []; if (toPage) currentIndex = (state.video?.videoInfo?.episode ?? 1) - 1; // for (var video in state.episodeList) { // if (video.isLock == true) { // state.curUnlock = state.episodeList.indexOf(video); // break; // } // } // reportHistory(); controllers = List.filled( state.episodeList.length, null, growable: true, ); // await _initializeController(currentIndex); // _preloadAdjacentVideos(); // if(currentIndex != 0){ if (toPage) { onPageChanged( currentIndex, isToggle: true, isUploadHistorySeconds: false, ); } else { _initializeController(currentIndex); } // } update(); } else { state.loadStatus = KtLoadStatusType.loadFailed; update(); } // if (userLogic.state.userInfo.isVip == true) state.curUnlock = 9999; update(); } catch (e) { // LottieLoading.close(); state.loadStatus = KtLoadStatusType.loadFailed; update(); } } void reportHistory() { if (currentIndex < 0 || currentIndex >= state.episodeList.length) return; Map params = { "short_play_id": state.shortPlayId, "video_id": state.episodeList[currentIndex].id, }; KtHttpClient().request(KtApis.createHistory, data: params); } void reportActivity() { Map params = { 'short_play_id': state.shortPlayId, "short_play_video_id": state.episodeList[currentIndex].shortPlayVideoId, "activity_id": state.activityId, }; KtHttpClient().request(KtApis.activeAfterWatchingVideo, data: params); } // 切换剧集时处理视频状态 Future onPageChanged( int index, { bool isToggle = false, bool isUploadHistorySeconds = true, int type = 0, }) async { // EasyThrottle.throttle('page-change', Duration(seconds: 3), () async { debugPrint('--$type-to-index:$index'); if (index < 0 || index >= state.episodeList.length) return; // 暂停当前视频 if (controllers[currentIndex]?.value.isPlaying ?? false) { await controllers[currentIndex]?.pause(); // if (isUploadHistorySeconds) uploadHistorySeconds(controllers[currentIndex]?.value.position.inMilliseconds ?? 0); } if (controllers[currentIndex]?.value.isCompleted ?? false) { // if (isUploadHistorySeconds) uploadHistorySeconds(0); if (state.activityId != null) reportActivity(); } if (isToggle) { // loadStatusType = LoadStatusType.loading; update(); await _initializeController(index); // loadStatusType = LoadStatusType.loadSuccess; update(); WidgetsBinding.instance.addPostFrameCallback((_) { pageController.jumpToPage(index); }); } currentIndex = index; // if (state.episodeList[index].isLock == true) { // controllers[index]?.seekTo(Duration(seconds: 0)); // controllers[index]?.pause(); // update(); // // showUnlockDialog(); // // // return; // } if (controllers[index] != null) { // if (state.curUnlock > index || userLogic.state.userInfo.isVip == true) { controllers[index]?.play(); // } } else { if (!isToggle) await _initializeController(index); // if (state.curUnlock > index || userLogic.state.userInfo.isVip == true) { controllers[index]?.play(); // } } controllers[index]?.setPlaybackSpeed(state.currentSpeed); // updateHomeVideo(); // print('----curIndex:$currentIndex'); // 预加载新的相邻视频,并释放多余控制器 _preloadAdjacentVideos(); update(); reportHistory(); // }); } // 释放非当前、前后的视频控制器,减少内存占用 void _releaseUnusedControllers() { for (int i = 0; i < controllers.length; i++) { if (i < currentIndex - 1 || i > currentIndex + 1) { controllers[i]?.dispose(); controllers[i] = null; } } } // 初始化视频控制器 Future _initializeController(int index) async { if (index < 0 || index >= state.episodeList.length) return; if (controllers[index] != null) return; final episode = state.episodeList[index]; VideoPlayerController controller = Platform.isAndroid && KtDeviceInfoUtil().osVersion == '10' ? VideoPlayerController.networkUrl( Uri.parse(episode.videoUrl!), formatHint: VideoFormat.hls, viewType: VideoViewType.platformView, ) : VideoPlayerController.networkUrl( Uri.parse(episode.videoUrl!), formatHint: VideoFormat.hls, ); controllers[index] = controller; try { await controller.initialize(); // if (index == currentIndex && (episode.isLock == false || userLogic.state.userInfo.isVip == true)) { if (index == currentIndex) { controller.play(); update(); } controller.setPlaybackSpeed(state.currentSpeed); debugPrint('---seekTo:${episode.playSeconds}'); controller.addListener(() { if (currentIndex == index && !_disposed) update(); if (currentIndex == state.episodeList.length - 1 && (controllers.last?.value.isCompleted ?? false)) { // showRecommendDialog(); } if (controller.value.isCompleted && !controller.value.isBuffering) { onPageChanged(index + 1, isToggle: true); } }); } catch (e) { // 可根据需要处理异常 // UserUtil().reportErrorEvent( // 'video initialize failed', // UserUtil.videoError, // errMsg: e.toString(), // payData: episode.toJson(), // shortPlayId: episode.shortPlayId ?? 0, // shortPlayVideoId: episode.shortPlayVideoId ?? 0, // ); debugPrint('---err:$e'); } } // 预加载相邻视频 void _preloadAdjacentVideos() { if (currentIndex > 0) _initializeController(currentIndex - 1); if (currentIndex < state.episodeList.length - 1) { _initializeController(currentIndex + 1); } _releaseUnusedControllers(); } Future likeVideo() async { if (state.video == null) return; Map params = { "short_play_id": state.video?.shortPlayInfo?.shortPlayId, "video_id": state.episodeList[currentIndex].id, }; if (state.video?.shortPlayInfo?.isCollect ?? false) { await KtHttpClient().request(KtApis.deleteFavoriteVideo, data: params); } else { await KtHttpClient().request(KtApis.collectVideo, data: params); } state.video?.shortPlayInfo?.isCollect = !(state.video?.shortPlayInfo?.isCollect ?? false); // update(['video-like']); // if (state.isFromDiscover) { // try { // final discoverLogic = Get.put(DiscoverLogic()); // discoverLogic.setCollectVideo( // state.video!.shortPlayInfo.shortPlayId!, // isCollect: state.video!.shortPlayInfo.isCollect!, // ); // } catch (e) { // debugPrint('---err:$e'); // } // } update(); } }