import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import 'package:maibu_satabot_v2/core/app/app_user_cubit.dart'; import 'package:maibu_satabot_v2/core/infrastructure/logging/app_bloc_observer.dart'; import 'package:maibu_satabot_v2/core/logging/i_logger_service.dart'; import 'package:maibu_satabot_v2/core/theme/AppTheme.dart'; import 'package:maibu_satabot_v2/features/auth/presentation/bloc/auth_cubit.dart'; import 'package:maibu_satabot_v2/features/devices/presentation/bloc/devices_cubit.dart'; import 'core/di/injection.dart'; import 'features/auth/presentation/bloc/auth_state.dart'; import 'features/auth/presentation/bloc/login_cubit.dart'; import 'features/devices/presentation/bloc/device_status_bloc.dart'; void main() async { // 1. 使用 runZonedGuarded 捕获所有未处理的异步错误 runZonedGuarded( () async { WidgetsFlutterBinding.ensureInitialized(); // 2. 初始化依赖注入 (这里面应包含 ILoggerService 的注册) await init(); // 3. 从 sl 中获取 logger 实例并初始化 Sentry final logger = sl(); await logger.init(); // 4. 设置全局 Bloc 观察者,自动上报 Bloc 错误 Bloc.observer = AppBlocObserver(logger); runApp(const MyApp()); }, (error, stack) { // 5. 捕获顶级错误并上报 sl().captureException(error, stackTrace: stack); }, ); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { // 在 runApp 之前调用 appStarted,确保 GoRouter 初始化时能获取到正确的初始状态 sl().appStarted(); final deviceStatusBloc = sl(); return MultiBlocProvider( providers: [ // 核心修正:在这里提供 AuthCubit BlocProvider(create: (_) => sl()), BlocProvider(create: (_) => sl()), BlocProvider(create: (_) => sl()), BlocProvider( create: (_) { // 增加一个健壮性检查 final user = sl().state.user; final devicesCubit = sl(); if (user != null) { devicesCubit.fetchAllDevices(user.username); } return devicesCubit; }, ), BlocProvider.value( value: deviceStatusBloc, ), // 其他 Cubit... ], child: MaterialApp.router(title: 'Maibu Satabot', theme: AppTheme.lightTheme, routerConfig: sl(), builder: (context, child) { return _LifecycleListener(child: child); },), ); } } // 🔥 新增:应用生命周期监听器 class _LifecycleListener extends StatefulWidget { final Widget? child; const _LifecycleListener({required this.child}); @override State<_LifecycleListener> createState() => _LifecycleListenerState(); } class _LifecycleListenerState extends State<_LifecycleListener> with WidgetsBindingObserver { @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); switch (state) { case AppLifecycleState.resumed: // 🔥 从息屏或后台恢复到前台 debugPrint('📱 [生命周期] 应用恢复到前台 (resumed),检查 TCP 连接...'); _handleResume(); break; case AppLifecycleState.inactive: // 应用处于非活动状态(iOS 来电、Android 分屏等) debugPrint('💤 [生命周期] 应用进入非活动状态 (inactive)'); break; case AppLifecycleState.paused: // 应用进入后台(息屏、按 Home 键等) debugPrint('🌙 [生命周期] 应用进入后台 (paused)'); break; case AppLifecycleState.detached: // 应用仍然托管但不会显示给用户(例如销毁中的 Activity) debugPrint('🚫 [生命周期] 应用已分离 (detached)'); break; case AppLifecycleState.hidden: // 应用不可见(Android 14+ 或未来版本) debugPrint('👻 [生命周期] 应用已隐藏 (hidden)'); break; } } // 🔥 处理恢复到前台的逻辑 Future _handleResume() async { try { final authCubit = context.read(); // 检查当前是否已登录 if (authCubit.state is! AuthAuthenticated) { debugPrint('⚠️ [生命周期] 用户未登录,跳过 TCP 重连'); return; } // 检查 TCP 连接状态 // 注意:这里需要通过 authCubit 访问 tcp 实例 // 由于 tcp 是 private 字段,我们需要在 AuthCubit 中暴露一个方法 debugPrint('✅ [生命周期] 准备执行 TCP 重连检查...'); // 延迟一点执行,确保 UI 已经加载完成 await Future.delayed(const Duration(milliseconds: 500)); // 调用 AuthCubit 的重连方法 await authCubit.reconnectAfterResume(); debugPrint('✅ [生命周期] TCP 重连检查完成'); } catch (e, stack) { debugPrint('❌ [生命周期] 重连过程发生错误:$e\n$stack'); } } @override Widget build(BuildContext context) { return widget.child!; } }