This commit is contained in:
lz_db
2026-10-25 13:26:40 +08:00
parent 494f667719
commit 7fae7387f5
6 changed files with 111 additions and 37 deletions
+66 -17
View File
@@ -1,7 +1,11 @@
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:media_kit/media_kit.dart';
import 'core/log/action_logger.dart';
import 'core/media/download_manager.dart';
import 'core/media/local_media_server.dart';
import 'core/storage/local_store.dart';
@@ -13,24 +17,69 @@ import 'router.dart';
/// App 入口:本地存储 + MediaKit + MaterialApp.router
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// 版本信息(版本检查/请求头 X-App-Version 依赖,必须先初始化)
await AppConfig.initVersion();
// MediaKit(libmpv 底层)全局初始化:每个进程必须且仅调一次
MediaKit.ensureInitialized();
// 本地存储初始化(设备指纹在 splash 阶段生成)
await LocalStore.init();
// 搜索历史(本地,不上报服务端)
await SearchHistoryStore.init();
// 观看上报去重(持久化;不初始化则观看计费/游客免费额度链路失效)
await WatchDedupStore.init();
// 本地媒体服务:HLS 1G 分片缓存(回看免下载)+ 已下载视频离线播放
await LocalMediaServer.I.init();
// 全局异常捕获:把 Dart 侧未捕获异常上报到操作日志(仅白名单用户启用)。
// 注意:原生层(mpv/内核)崩溃这里捕获不到,只能拿到 Dart/Framework 层。
runZonedGuarded(() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(ProviderScope(
overrides: const [],
child: const _AppInitializer(),
));
// Flutter Framework 错误(build/layout/paint 阶段抛出)
FlutterError.onError = (details) {
FlutterError.presentError(details);
ActionLogger.I.log(
'crash_flutter_error',
page: 'app',
detail: {
'exception': details.exceptionAsString(),
'library': details.library ?? '',
'stack': (details.stack ?? StackTrace.empty).toString().split('\n').take(20).join('\n'),
},
);
unawaited(ActionLogger.I.flush());
};
// Dart 异步/平台通道未捕获错误
ui.PlatformDispatcher.instance.onError = (error, stack) {
ActionLogger.I.log(
'crash_platform_error',
page: 'app',
detail: {
'exception': error.toString(),
'stack': stack.toString().split('\n').take(20).join('\n'),
},
);
unawaited(ActionLogger.I.flush());
return true;
};
// 版本信息(版本检查/请求头 X-App-Version 依赖,必须先初始化)
await AppConfig.initVersion();
// MediaKit(libmpv 底层)全局初始化:每个进程必须且仅调一次
MediaKit.ensureInitialized();
// 本地存储初始化(设备指纹在 splash 阶段生成)
await LocalStore.init();
// 搜索历史(本地,不上报服务端)
await SearchHistoryStore.init();
// 观看上报去重(持久化;不初始化则观看计费/游客免费额度链路失效)
await WatchDedupStore.init();
// 本地媒体服务:HLS 1G 分片缓存(回看免下载)+ 已下载视频离线播放
await LocalMediaServer.I.init();
runApp(ProviderScope(
overrides: const [],
child: const _AppInitializer(),
));
}, (error, stack) {
// Zone 内未捕获错误(一般与 PlatformDispatcher 重叠,双保险)
ActionLogger.I.log(
'crash_zone',
page: 'app',
detail: {
'exception': error.toString(),
'stack': stack.toString().split('\n').take(20).join('\n'),
},
);
unawaited(ActionLogger.I.flush());
});
}
/// 初始化需要 Provider 环境的单例(下载管理器扫描本地已下载列表)
+20 -13
View File
@@ -130,23 +130,30 @@ class _FeedScreenState extends ConsumerState<FeedScreen>
.read(feedProvider(_strategy).notifier)
.events
.listen(_handleEvent);
// 保留每个策略的播放进度(currentIndex 由 provider 维护):切回时跳到上次位置而非归零
final targetIndex = ref.read(feedProvider(_strategy)).currentIndex;
if (_pageController.hasClients && targetIndex > 0) {
_pageController.jumpToPage(targetIndex);
} else if (_pageController.hasClients) {
_pageController.jumpToPage(0);
}
// jumpToPage 后 resume + rebindCurrent:suspend 已 stop 槽位,仅 play
// 播不起来,必须 rebind 重新 open(有断点记录则 seek 续播)
ActionLogger.I.log('feed_switch_strategy', page: '/home', detail: {
'to': next.name,
'target': targetIndex,
'liked': ref.read(feedProvider(FeedStrategy.liked)).currentIndex,
'viewed': ref.read(feedProvider(FeedStrategy.viewed)).currentIndex,
});
// 必须等新策略的 PageView 重建完成后再跳页:同步 jumpToPage 触发的是
// 旧 PageView 的 onPageChanged(回调仍指向旧策略 notifier),会把旧策略的
// currentIndex 改成 0,导致切回时从第 1 条开始播
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
unawaited(() async {
final n = ref.read(feedProvider(_strategy).notifier);
await n.pool.resume();
await n.rebindCurrent();
}());
if (!mounted) return;
if (_pageController.hasClients) {
_pageController.jumpToPage(targetIndex);
}
// jumpToPage 后 resume + rebindCurrent:suspend 已 stop 槽位,仅 play
// 播不起来,必须 rebind 重新 open(有断点记录则 seek 续播)
unawaited(() async {
final n = ref.read(feedProvider(_strategy).notifier);
await n.pool.resume();
await n.rebindCurrent();
}());
});
}
+1 -1
View File
@@ -2,7 +2,7 @@ name: video_app
description: "短视频应用(Flutter,iOS/Android 双端)"
publish_to: 'none'
version: 1.3.28+44
version: 1.3.31+47
environment:
sdk: ^3.9.2