app.dart 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_riverpod/flutter_riverpod.dart';
  3. import 'package:sino_med_cloud/core/network/network_provider.dart';
  4. import 'package:sino_med_cloud/l10n/app_localizations.dart';
  5. import 'package:sino_med_cloud/shared/widgets/loading_view.dart';
  6. import '../core/constants/app_enum.dart';
  7. import 'router.dart';
  8. import 'theme.dart';
  9. class SinoMedApp extends ConsumerStatefulWidget {
  10. const SinoMedApp({super.key});
  11. @override
  12. ConsumerState<SinoMedApp> createState() => _SinoMedAppState();
  13. }
  14. class _SinoMedAppState extends ConsumerState<SinoMedApp> {
  15. @override
  16. Widget build(BuildContext context) {
  17. // 监听网络状态变化并自动导航
  18. // ref.listen 必须在 build 方法中使用
  19. ref.listen(networkStatusProvider, (previous, next) {
  20. next.whenData((status) {
  21. final router = AppRouter.router;
  22. try {
  23. // 获取当前路由路径
  24. // 注意:如果 router 还没准备好,这里可能会报错,所以加了 try-catch
  25. final matchList = router.routerDelegate.currentConfiguration.matches;
  26. final currentLocation = matchList.isNotEmpty
  27. ? matchList.last.matchedLocation
  28. : router.routerDelegate.currentConfiguration.uri.path;
  29. // 判断网络是否正常(WiFi 和移动网络都视为正常)
  30. final isNetworkAvailable = status == NetworkStatus.wifi || status == NetworkStatus.mobile;
  31. if (isNetworkAvailable) {
  32. // 网络正常:如果当前在无网络页面,则返回到之前保存的页面
  33. if (currentLocation == '/noNetwork') {
  34. final previousPath = ref.read(previousPagePathProvider);
  35. final targetPath = previousPath ?? '/'; // 如果没有保存的页面,则返回登录页
  36. // 使用 addPostFrameCallback 避免在构建过程中导航
  37. WidgetsBinding.instance.addPostFrameCallback((_) {
  38. if (mounted) {
  39. router.go(targetPath);
  40. // 清除保存的页面路径
  41. ref.read(previousPagePathProvider.notifier).state = null;
  42. }
  43. });
  44. }
  45. // 如果网络正常且不在无网络页面,则停留在当前页面
  46. } else {
  47. // 网络不正常(无网络):保存当前页面并导航到无网络页面
  48. if (currentLocation != '/noNetwork') {
  49. // 保存当前页面路径(如果当前不在无网络页面)
  50. ref.read(previousPagePathProvider.notifier).state = currentLocation;
  51. WidgetsBinding.instance.addPostFrameCallback((_) {
  52. if (mounted) {
  53. router.go('/noNetwork');
  54. }
  55. });
  56. }
  57. }
  58. } catch (e) {
  59. // 如果无法获取当前路由,根据网络状态直接处理
  60. final isNetworkAvailable = status == NetworkStatus.wifi || status == NetworkStatus.mobile;
  61. if (!isNetworkAvailable) {
  62. WidgetsBinding.instance.addPostFrameCallback((_) {
  63. if (mounted) {
  64. router.go('/noNetwork');
  65. }
  66. });
  67. }
  68. }
  69. });
  70. });
  71. final networkAsync = ref.watch(networkStatusProvider);
  72. return networkAsync.when(
  73. loading: () {
  74. // Loading 状态显示加载指示器
  75. return MaterialApp(
  76. debugShowCheckedModeBanner: false,
  77. theme: AppTheme.light,
  78. home: const Scaffold(
  79. body: LoadingView(),
  80. ),
  81. );
  82. },
  83. error: (error, _) {
  84. return _materialApp;
  85. },
  86. data: (_) {
  87. return _materialApp;
  88. },
  89. );
  90. }
  91. MaterialApp get _materialApp => MaterialApp.router(
  92. onGenerateTitle: (context) => AppLocalizations.of(context)?.appSubtitle ?? '中方诊药云',
  93. theme: AppTheme.light,
  94. routerConfig: AppRouter.router,
  95. debugShowCheckedModeBanner: false,
  96. localizationsDelegates: AppLocalizations.localizationsDelegates,
  97. supportedLocales: AppLocalizations.supportedLocales,
  98. locale: const Locale('zh'),
  99. );
  100. }