382 lines
13 KiB
Dart
382 lines
13 KiB
Dart
import 'dart:async';
|
||
import 'dart:io';
|
||
import 'dart:ui';
|
||
|
||
import 'package:firebase_core/firebase_core.dart';
|
||
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
||
import 'package:fluro/fluro.dart' as fluro;
|
||
import 'package:flutter/cupertino.dart';
|
||
import 'package:flutter/gestures.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter/foundation.dart';
|
||
import 'package:flutter/services.dart';
|
||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||
import 'package:yumi/shared/tools/sc_keybord_util.dart';
|
||
import 'package:yumi/shared/data_sources/sources/local/data_persistence.dart';
|
||
import 'package:provider/provider.dart';
|
||
import 'package:provider/single_child_widget.dart';
|
||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||
|
||
import 'app_localizations.dart';
|
||
import 'app/config/app_config.dart';
|
||
import 'app/constants/sc_global_config.dart';
|
||
import 'app/constants/sc_screen.dart';
|
||
import 'app/routes/sc_routes.dart';
|
||
import 'app/routes/sc_lk_application.dart';
|
||
import 'shared/tools/sc_deep_link_handler.dart';
|
||
import 'shared/tools/sc_deviceId_utils.dart';
|
||
import 'modules/splash/splash_page.dart';
|
||
import 'services/general/sc_app_general_manager.dart';
|
||
import 'services/payment/apple_payment_manager.dart';
|
||
import 'services/auth/authentication_manager.dart';
|
||
import 'services/gift/gift_animation_manager.dart';
|
||
import 'services/gift/gift_system_manager.dart';
|
||
import 'services/payment/google_payment_manager.dart';
|
||
import 'services/localization/localization_manager.dart';
|
||
import 'services/room/rc_room_manager.dart';
|
||
import 'services/audio/rtc_manager.dart';
|
||
import 'services/audio/rtm_manager.dart';
|
||
import 'services/shop/shop_manager.dart';
|
||
import 'services/theme/theme_manager.dart';
|
||
import 'services/auth/user_profile_manager.dart';
|
||
import 'ui_kit/theme/socialchat_theme.dart';
|
||
|
||
|
||
void main() async {
|
||
|
||
// 初始化应用配置
|
||
AppConfig.initialize();
|
||
|
||
|
||
// 2. 使用 runZonedGuarded 创建一个隔离区域来捕获所有异步错误
|
||
runZonedGuarded(
|
||
() async {
|
||
// 1. 确保 Widget 绑定初始化
|
||
WidgetsFlutterBinding.ensureInitialized();
|
||
// 性能优化:启用手势重采样
|
||
GestureBinding.instance.resamplingEnabled = true;
|
||
// 阶段1:初始化绝对必要的服务(不阻塞UI)
|
||
await _setupA();
|
||
// 使用重试机制初始化存储
|
||
await _initStore();
|
||
// 立即运行应用,不等待非必要服务初始化
|
||
runApp(const RootAppWithProviders());
|
||
},
|
||
// 9. runZonedGuarded 的错误回调(这是捕获异步错误的主要方式)
|
||
(error, stackTrace) {
|
||
// 这是捕获 runZonedGuarded 区域内所有未捕获异步错误的地方
|
||
FirebaseCrashlytics.instance.recordError(error, stackTrace, fatal: true);
|
||
debugPrint('Zoned Error: $error\nStack: $stackTrace');
|
||
},
|
||
);
|
||
}
|
||
|
||
/// 设置核心服务(重命名自_initializeEssentialServices)
|
||
Future<void> _setupA() async {
|
||
// 配置设备方向:仅竖屏
|
||
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||
|
||
// Android平台状态栏样式设置
|
||
if (Platform.isAndroid) {
|
||
SystemChrome.setSystemUIOverlayStyle(
|
||
const SystemUiOverlayStyle(
|
||
statusBarColor: Colors.transparent,
|
||
statusBarIconBrightness: Brightness.dark,
|
||
),
|
||
);
|
||
}
|
||
|
||
// 键盘工具初始化
|
||
SCKeybordUtil.init();
|
||
|
||
// Firebase核心初始化(必需组件)
|
||
try {
|
||
await Firebase.initializeApp();
|
||
if (kDebugMode) {
|
||
debugPrint('Firebase初始化完成');
|
||
}
|
||
} catch (e, stackTrace) {
|
||
debugPrint('Firebase初始化异常: $e\n$stackTrace');
|
||
// 非阻塞错误处理:记录但继续运行
|
||
}
|
||
|
||
// Flutter错误拦截器配置
|
||
FlutterError.onError = (details) {
|
||
FirebaseCrashlytics.instance.recordFlutterFatalError(details);
|
||
FlutterError.presentError(details);
|
||
};
|
||
|
||
// 平台层错误处理器
|
||
PlatformDispatcher.instance.onError = (error, stack) {
|
||
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
|
||
return true; // 错误已处理
|
||
};
|
||
|
||
// 启用崩溃收集
|
||
await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
|
||
}
|
||
|
||
|
||
/// 带重试的数据存储初始化(重命名自_initializeStorageWithRetry)
|
||
Future<void> _initStore() async {
|
||
const maxAttempts = 3;
|
||
int attemptCount = 0;
|
||
bool success = false;
|
||
|
||
while (attemptCount < maxAttempts && !success) {
|
||
attemptCount++;
|
||
try {
|
||
await DataPersistence.initialize();
|
||
success = true;
|
||
if (kDebugMode) {
|
||
debugPrint('数据存储初始化成功(尝试次数: $attemptCount)');
|
||
}
|
||
} catch (e) {
|
||
debugPrint('数据存储初始化尝试 $attemptCount 失败: $e');
|
||
|
||
if (attemptCount >= maxAttempts) {
|
||
debugPrint('数据存储初始化失败,已达最大重试次数: $maxAttempts');
|
||
// 不抛出异常,允许应用继续运行
|
||
return;
|
||
}
|
||
|
||
// 递增延迟:500ms, 1000ms, 1500ms...
|
||
int delayMs = 500 * attemptCount;
|
||
await Future.delayed(Duration(milliseconds: delayMs));
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 带有所有Provider的根组件
|
||
class RootAppWithProviders extends StatelessWidget {
|
||
const RootAppWithProviders({super.key});
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return MultiProvider(providers: _buildP(), child: const YumiApplication());
|
||
}
|
||
|
||
/// 构建应用Provider列表 - 重新排序以优化性能
|
||
List<SingleChildWidget> _buildP() {
|
||
return [
|
||
// 核心用户相关Provider - 必须立即初始化
|
||
ChangeNotifierProvider<SocialChatAuthenticationManager>(
|
||
lazy: false,
|
||
create: (context) => SocialChatAuthenticationManager(),
|
||
),
|
||
ChangeNotifierProvider<SocialChatUserProfileManager>(
|
||
lazy: false,
|
||
create: (context) => SocialChatUserProfileManager(),
|
||
),
|
||
|
||
// UI与主题相关Provider - 懒加载
|
||
ChangeNotifierProvider<ThemeManager>(
|
||
lazy: true,
|
||
create: (context) => ThemeManager(),
|
||
),
|
||
ChangeNotifierProvider<LocalizationManager>(
|
||
lazy: true,
|
||
create: (context) => LocalizationManager(),
|
||
),
|
||
|
||
// 实时通信Provider - 懒加载
|
||
ChangeNotifierProvider<RtcProvider>(
|
||
lazy: true,
|
||
create: (context) => RealTimeCommunicationManager(),
|
||
),
|
||
ChangeNotifierProvider<RtmProvider>(
|
||
lazy: true,
|
||
create: (context) => RealTimeMessagingManager(),
|
||
),
|
||
|
||
// 房间与社交功能Provider - 懒加载
|
||
ChangeNotifierProvider<SocialChatRoomManager>(
|
||
lazy: true,
|
||
create: (context) => SocialChatRoomManager(),
|
||
),
|
||
|
||
// 礼物与动画系统Provider - 懒加载
|
||
ChangeNotifierProvider<GiftProvider>(
|
||
lazy: true,
|
||
create: (context) => SocialChatGiftSystemManager(),
|
||
),
|
||
ChangeNotifierProvider<GiftAnimationManager>(
|
||
lazy: true,
|
||
create: (context) => GiftAnimationManager(),
|
||
),
|
||
|
||
// 支付与商店Provider - 懒加载
|
||
ChangeNotifierProvider<AndroidPaymentProcessor>(
|
||
lazy: true,
|
||
create: (context) => AndroidPaymentProcessor(),
|
||
),
|
||
ChangeNotifierProvider<IOSPaymentProcessor>(
|
||
lazy: true,
|
||
create: (context) => IOSPaymentProcessor(),
|
||
),
|
||
ChangeNotifierProvider<ShopManager>(
|
||
lazy: true,
|
||
create: (context) => ShopManager(),
|
||
),
|
||
|
||
|
||
// 通用应用管理Provider - 懒加载
|
||
ChangeNotifierProvider<SCAppGeneralManager>(
|
||
lazy: true,
|
||
create: (context) => SCAppGeneralManager(),
|
||
),
|
||
];
|
||
}
|
||
}
|
||
|
||
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||
final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
|
||
|
||
class YumiApplication extends StatefulWidget {
|
||
const YumiApplication({super.key});
|
||
|
||
@override
|
||
State<YumiApplication> createState() => _YumiApplicationState();
|
||
}
|
||
|
||
class _YumiApplicationState extends State<YumiApplication> {
|
||
late fluro.FluroRouter _router;
|
||
final SCDeepLinkHandler _deepLinkHandler = SCDeepLinkHandler();
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
// 初始化深层链接处理
|
||
_initLink();
|
||
// 延迟初始化路由和设备信息
|
||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||
_initRouter();
|
||
SCDeviceIdUtils.initDeviceinfo();
|
||
});
|
||
}
|
||
|
||
@override
|
||
dispose() {
|
||
_deepLinkHandler.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
Future<void> _initLink() async {
|
||
// 初始化,并传递一个回调函数用于处理链接
|
||
await _deepLinkHandler.initDeepLinks(
|
||
onLinkReceived: (Uri uri) {
|
||
// 当收到链接时,无论应用在哪个页面,都可以进行路由
|
||
_handleLink(uri);
|
||
},
|
||
);
|
||
}
|
||
|
||
void _handleLink(Uri uri) {
|
||
// 这是处理链接的核心路由逻辑
|
||
print('App 根层收到链接: $uri');
|
||
String path = uri.path;
|
||
String id = uri.queryParameters['id'] ?? '';
|
||
}
|
||
|
||
void _initRouter() {
|
||
_router = fluro.FluroRouter();
|
||
SCRoutes.configureRoutes(_router);
|
||
SCLkApplication.router = _router;
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return _buildUI();
|
||
}
|
||
|
||
// 构建下拉刷新配置的页脚部件
|
||
Widget Function() _buildFooter() {
|
||
return () => CustomFooter(
|
||
builder: (BuildContext context, LoadStatus? mode) {
|
||
Widget body;
|
||
if (mode == LoadStatus.idle) {
|
||
body = Text(
|
||
SCAppLocalizations.of(context)!.pullToLoadMore,
|
||
);
|
||
} else if (mode == LoadStatus.loading) {
|
||
body = CupertinoActivityIndicator(color: Colors.white24);
|
||
} else if (mode == LoadStatus.failed) {
|
||
body = Text(
|
||
SCAppLocalizations.of(context)!.loadingFailedClickToRetry,
|
||
);
|
||
} else if (mode == LoadStatus.canLoading) {
|
||
body = Text(
|
||
SCAppLocalizations.of(context)!.releaseToLoadMore,
|
||
);
|
||
} else {
|
||
body = Text(
|
||
"",
|
||
style: TextStyle(
|
||
fontSize: 12.sp,
|
||
color: Color(0xff999999),
|
||
),
|
||
);
|
||
}
|
||
return Container(
|
||
height: kTextTabBarHeight + ScreenUtil().statusBarHeight,
|
||
child: Center(child: body),
|
||
);
|
||
},
|
||
);
|
||
}
|
||
|
||
|
||
Widget _buildUI() {
|
||
return Consumer<LocalizationManager>(
|
||
builder: (context, localeProvider, child) {
|
||
// 只有在LocaleProvider可用时才设置语言
|
||
SCGlobalConfig.lang = localeProvider.locale?.languageCode ?? "en";
|
||
return Consumer<ThemeManager>(
|
||
builder: (context, themeManager, child) {
|
||
return ScreenUtilInit(
|
||
designSize: Size(SCScreen.designWidth, SCScreen.designHeight),
|
||
splitScreenMode: false,
|
||
minTextAdapt: true,
|
||
builder: (context, child) {
|
||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||
value: SystemUiOverlayStyle.dark,
|
||
child: RefreshConfiguration(
|
||
headerBuilder: () => MaterialClassicHeader(color: SocialChatTheme.primaryColor),
|
||
footerBuilder: _buildFooter(),
|
||
child: MaterialApp(
|
||
title: 'Yumi',
|
||
locale: Provider.of<LocalizationManager>(context).locale,
|
||
localizationsDelegates: [
|
||
SCAppLocalizations.delegate,
|
||
GlobalMaterialLocalizations.delegate,
|
||
GlobalCupertinoLocalizations.delegate,
|
||
GlobalWidgetsLocalizations.delegate,
|
||
],
|
||
supportedLocales: [
|
||
const Locale('en', ''),
|
||
const Locale('zh', ''),
|
||
const Locale('ar', ''),
|
||
const Locale('tr', ''),
|
||
const Locale('bn', ''),
|
||
],
|
||
navigatorKey: navigatorKey,
|
||
debugShowCheckedModeBanner: false,
|
||
onGenerateRoute: SCLkApplication.router.generator,
|
||
theme: themeManager.currentTheme,
|
||
home: SplashPage(),
|
||
builder: FlutterSmartDialog.init(),
|
||
navigatorObservers: [routeObserver],
|
||
),
|
||
),
|
||
);
|
||
},
|
||
);
|
||
},
|
||
);
|
||
},
|
||
);
|
||
}
|
||
}
|