Files
kitchen/lib/main.dart
2026-04-15 07:11:28 +08:00

193 lines
5.5 KiB
Dart

import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:get/get.dart';
import 'package:catcher_2/catcher_2.dart';
import 'package:mom_kitchen/src/l10n/app_localizations.dart';
import 'package:mom_kitchen/src/config/app_routes.dart';
import 'package:mom_kitchen/src/services/core/app_service.dart';
import 'package:mom_kitchen/src/services/orientation_service.dart';
import 'package:mom_kitchen/src/services/ui/theme_service.dart';
import 'package:mom_kitchen/src/services/ui/toast_service.dart';
import 'package:mom_kitchen/src/services/crash_guard_service.dart';
import 'package:mom_kitchen/src/app_binding.dart';
import 'package:mom_kitchen/src/utils/app_logger.dart';
// 2026-04-15 | main.dart | 应用入口 | Catcher2最先初始化+串行化启动流程防ANR
void main() {
final crashGuard = CrashGuardService();
Catcher2(
runAppFunction: () async {
WidgetsFlutterBinding.ensureInitialized();
await _initApp();
runApp(const MyApp());
},
ensureInitialized: false,
debugConfig: crashGuard.buildDebugOptions(),
releaseConfig: crashGuard.buildReleaseOptions(),
);
}
Future<void> _initApp() async {
try {
await AppService.instance.init();
} catch (e) {
debugPrint('❌ AppService初始化失败: $e');
}
try {
await CrashGuardService.init();
} catch (e) {
debugPrint('⚠️ CrashGuardService初始化失败: $e');
}
if (kDebugMode) {
AppRoutes.registerAllPages();
}
await OrientationService().unlockOrientation();
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
final themeService = Get.put(ThemeService.instance);
return Obx(() {
final textScale = themeService.fontSize.value / 16.0;
return GetCupertinoApp(
title: 'Mom\'s Kitchen',
navigatorKey: Catcher2.navigatorKey,
theme: themeService.cupertinoThemeData,
locale: Locale(themeService.currentLocale.value),
debugShowCheckedModeBanner: false,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: const [
Locale('en'),
Locale('zh'),
Locale('zh', 'Hant'),
],
getPages: AppRoutes.pages,
initialBinding: AppBinding(),
builder: (context, widget) {
return MediaQuery(
data: MediaQuery.of(
context,
).copyWith(textScaler: TextScaler.linear(textScale)),
child: ColoredBox(
color: themeService.backgroundColor.value,
child: widget ?? const SizedBox.shrink(),
),
);
},
routingCallback: (routing) {
if (kDebugMode && routing?.current != null) {
AppLogger.d('🔍 路由变化: ${routing?.previous}${routing?.current}');
}
},
home: const _InitWrapper(),
);
});
}
}
class _InitWrapper extends StatefulWidget {
const _InitWrapper();
@override
State<_InitWrapper> createState() => _InitWrapperState();
}
class _InitWrapperState extends State<_InitWrapper>
with WidgetsBindingObserver {
bool _navigated = false;
int _retryCount = 0;
static const int _maxRetries = 3;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
_navigateToMain();
}
void _navigateToMain() {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted || _navigated) return;
try {
ToastService.init(context);
Get.offAllNamed(AppRoutes.main);
_navigated = true;
debugPrint('✅ 导航到主页面成功');
} catch (e) {
_retryCount++;
debugPrint('❌ 导航失败 (第$_retryCount次): $e');
if (_retryCount < _maxRetries) {
Future.delayed(Duration(milliseconds: 500 * _retryCount), () {
if (mounted && !_navigated) _navigateToMain();
});
} else {
debugPrint('🚨 导航重试已达上限,显示错误页面');
if (mounted) setState(() {});
}
}
});
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangePlatformBrightness() {
super.didChangePlatformBrightness();
final brightness =
WidgetsBinding.instance.platformDispatcher.platformBrightness;
try {
final themeService = Get.find<ThemeService>();
themeService.onSystemBrightnessChanged(brightness);
} catch (_) {}
}
@override
Widget build(BuildContext context) {
if (_retryCount >= _maxRetries) {
return CupertinoPageScaffold(
child: SafeArea(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(CupertinoIcons.exclamationmark_triangle, size: 48),
const SizedBox(height: 16),
const Text('启动失败,请重试', style: TextStyle(fontSize: 16)),
const SizedBox(height: 24),
CupertinoButton.filled(
onPressed: () {
_retryCount = 0;
_navigateToMain();
},
child: const Text('重试'),
),
],
),
),
),
);
}
return const CupertinoPageScaffold(
child: Center(child: CupertinoActivityIndicator()),
);
}
}