后台播放能力已调通,介入部分细节优化

This commit is contained in:
2026-08-20 22:36:10 +08:00
parent f94cda4234
commit bb8e4caf48
2 changed files with 303 additions and 49 deletions
+189
View File
@@ -0,0 +1,189 @@
// lib/services/app_lifecycle_manager.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:media_kit/media_kit.dart';
/// App 生命周期状态(扩展了 Flutter 原生状态)
enum AppLifecycleStatus {
/// 应用正在启动(初始化阶段)
launching,
/// 应用在前台,用户可交互
resumed,
/// 应用在前台但不可交互(如:来电、系统弹窗)
inactive,
/// 应用在后台
paused,
/// 应用即将被销毁
detached,
/// 应用已进入后台且播放停止(自定义,用于播放策略)
backgroundIdle,
}
/// App 生命周期管理器
///
/// 职责:
/// 1. 统一监听 Flutter 的 AppLifecycleState
/// 2. 管理播放器在前后台的行为
/// 3. 管理渲染调度器的运行状态
/// 4. 管理 WebDAV 的缓存策略
class AppLifecycleManager extends ChangeNotifier {
static final AppLifecycleManager _instance = AppLifecycleManager._internal();
factory AppLifecycleManager() => _instance;
AppLifecycleManager._internal();
// ---- 当前状态 ----
AppLifecycleStatus _status = AppLifecycleStatus.launching;
AppLifecycleStatus get status => _status;
// ---- 上次进入后台的时间 ----
DateTime? _backgroundedAt;
DateTime? get backgroundedAt => _backgroundedAt;
// ---- 是否在后台 ----
bool get isInBackground =>
_status == AppLifecycleStatus.paused ||
_status == AppLifecycleStatus.inactive ||
_status == AppLifecycleStatus.detached;
bool get isInForeground => _status == AppLifecycleStatus.resumed;
// ---- 后台时长 ----
Duration get backgroundDuration {
if (_backgroundedAt == null) return Duration.zero;
return DateTime.now().difference(_backgroundedAt!);
}
// ---- 是否处于"长后台"(超过 5 分钟) ----
bool get isLongBackground => backgroundDuration > const Duration(minutes: 5);
// ---- 监听器 ----
final List<void Function(AppLifecycleStatus)> _listeners = [];
// ---- Flutter 原生生命周期订阅 ----
late final WidgetsBindingObserver _observer;
bool _isObserving = false;
// ---- 初始化 ----
void init() {
if (_isObserving) return;
_isObserving = true;
_observer = _AppLifecycleObserver(this);
WidgetsBinding.instance.addObserver(_observer);
// 获取初始状态
_updateStatus(AppLifecycleStatus.resumed);
debugPrint('📱 AppLifecycleManager 已初始化');
}
// ---- 状态更新 ----
void _handleNativeState(AppLifecycleState state) {
final newStatus = _convertNativeState(state);
// 状态变化时更新
if (newStatus != _status) {
_updateStatus(newStatus);
}
// 记录进入后台的时间
if (newStatus == AppLifecycleStatus.paused ||
newStatus == AppLifecycleStatus.inactive) {
if (_backgroundedAt == null) {
_backgroundedAt = DateTime.now();
debugPrint('📱 App 进入后台: ${_backgroundedAt}');
}
}
// 回到前台时,如果是长后台,触发通知
if (newStatus == AppLifecycleStatus.resumed) {
if (_backgroundedAt != null) {
final duration = backgroundDuration;
debugPrint('📱 App 回到前台,后台时长: ${duration.inMinutes}分钟');
_backgroundedAt = null;
// 如果是长后台,通知监听器做重连等操作
if (duration > const Duration(minutes: 5)) {
_notifyListeners(AppLifecycleStatus.backgroundIdle);
}
}
}
}
void _updateStatus(AppLifecycleStatus newStatus) {
final oldStatus = _status;
_status = newStatus;
debugPrint('📱 生命周期状态变化: $oldStatus$newStatus');
notifyListeners();
_notifyListeners(newStatus);
}
AppLifecycleStatus _convertNativeState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.resumed:
return AppLifecycleStatus.resumed;
case AppLifecycleState.inactive:
return AppLifecycleStatus.inactive;
case AppLifecycleState.paused:
return AppLifecycleStatus.paused;
case AppLifecycleState.detached:
return AppLifecycleStatus.detached;
default:
return AppLifecycleStatus.paused;
}
}
// ---- 自定义监听器管理 ----
void addListenerToManager(void Function(AppLifecycleStatus) listener) {
_listeners.add(listener);
}
void removeListenerFromManager(void Function(AppLifecycleStatus) listener) {
_listeners.remove(listener);
}
void _notifyListeners(AppLifecycleStatus status) {
for (final listener in _listeners) {
try {
listener(status);
} catch (e) {
debugPrint('❌ 生命周期监听器执行失败: $e');
}
}
}
// ---- 检查是否需要重新连接 WebDAV ----
bool get shouldRecheckWebDAV {
if (!isInForeground) return false;
if (_backgroundedAt == null) return false;
return isLongBackground;
}
// ---- 释放 ----
void dispose() {
if (_isObserving) {
WidgetsBinding.instance.removeObserver(_observer);
_isObserving = false;
}
_listeners.clear();
super.dispose();
}
}
/// 内部观察者(绑定 WidgetsBinding
class _AppLifecycleObserver extends WidgetsBindingObserver {
final AppLifecycleManager _manager;
_AppLifecycleObserver(this._manager);
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
_manager._handleNativeState(state);
}
}