190 lines
5.4 KiB
Dart
190 lines
5.4 KiB
Dart
// 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);
|
||
}
|
||
}
|