Flutter Web已认证状态下首页重复加载两次的问题排查求助
Flutter Web已认证状态下首页重复加载两次的问题排查求助
我现在在开发一个Flutter Web应用,用了Bloc状态管理。我做了一个authOrApp路由用来检查用户是否已认证,但每次启动Web应用时,如果用户是已认证状态,首页会快速加载两次。问题在于首页里还有另一个Bloc要做比较重的处理,加载两次直接导致整个过程变慢了。我自己没找出原因,想请教下大家有没有什么排查思路?
下面是我的main.dart代码:
import 'dart:io'; import 'package:envelog/manage_users/bloc/manage_users_bloc.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; import 'package:http/io_client.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:envelog/auth_or_app/bloc/auth_or_app_bloc.dart'; import 'package:envelog/values/bloc/values_bloc.dart'; import 'package:envelog/values/models/values.dart'; import 'package:envelog/excerpt/bloc/excerpt_bloc.dart'; import 'package:envelog/excerpt/models/excerpt.dart'; import 'package:envelog/expense/bloc/expense_bloc.dart'; import 'package:envelog/expense/models/expense.dart'; import 'package:envelog/login/bloc/login_bloc.dart'; import 'package:envelog/login/models/logged_user.dart'; import 'package:envelog/nfc/bloc/nfc_bloc.dart'; import 'package:envelog/nfc/models/nfc.dart'; import 'package:envelog/observation/bloc/observation_bloc.dart'; import 'package:envelog/observation/models/observation.dart'; import 'package:envelog/refuel/bloc/refuel_bloc.dart'; import 'package:envelog/refuel/models/refuel.dart'; import 'package:envelog/side_menu/bloc/side_menu_bloc.dart'; import 'package:envelog/trip/bloc/trip_bloc.dart'; import 'package:envelog/trip/models/trip.dart'; import 'package:envelog/utils/app_routes.dart'; // ignore: depend_on_referenced_packages import 'package:flutter_localizations/flutter_localizations.dart'; final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); void main() async { await Hive.initFlutter(); await hiveAdapters(); // await Hive.deleteBoxFromDisk('pendingNfcOperations'); // substitua pelo nome correto da box await Hive.openBox<LoggedUser>('loggedUser'); await Hive.openBox<Trip>('trips'); await Hive.openBox<Nfc>('nfcs'); await Hive.openBox<Values>('values'); await Hive.openBox<Refuel>('refuels'); await Hive.openBox<Observation>('observations'); await Hive.openBox<Excerpt>('excerpts'); await Hive.openBox<Expense>('expenses'); await Hive.openBox<Map>('pendingTripOperations'); await Hive.openBox<Map>('pendingValuesOperations'); await Hive.openBox<Map>('pendingNfcOperations'); await Hive.openBox<Map>('pendingExcerptOperations'); await Hive.openBox<Map>('pendingExpenseOperations'); await Hive.openBox<Map>('pendingRefuelOperations'); await Hive.openBox<Map>('pendingObservationOperations'); HttpOverrides.global = MyHttpOverrides(); runApp(const MyApp()); } Future<void> hiveAdapters() async { Hive.registerAdapter(LoggedUserAdapter()); Hive.registerAdapter(TripAdapter()); Hive.registerAdapter(ExcerptAdapter()); Hive.registerAdapter(ExpenseAdapter()); Hive.registerAdapter(NfcAdapter()); Hive.registerAdapter(RefuelAdapter()); Hive.registerAdapter(ObservationAdapter()); Hive.registerAdapter(ValuesAdapter()); } class MyHttpOverrides extends HttpOverrides { @override HttpClient createHttpClient(SecurityContext? context) { final client = super.createHttpClient(context); client.badCertificateCallback = (X509Certificate cert, String host, int port) => true; return client; } } http.Client createHttpClientWithBypass() { final ioClient = HttpClient() ..badCertificateCallback = (X509Certificate cert, String host, int port) => true; return IOClient(ioClient); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MultiBlocProvider( providers: [ BlocProvider( create: (context) => LoginBloc(), ), if (!kIsWeb) BlocProvider( create: (context) => AuthOrAppBloc(), ), if (kIsWeb) BlocProvider( create: (context) => AuthOrAppBloc()..add(AuthOrAppInitialEvent()), ), BlocProvider( create: (context) => SideMenuBloc(), ), BlocProvider( create: (context) => TripBloc()..add(TripInitialEvent()), ), BlocProvider( create: (context) => ExcerptBloc(), ), BlocProvider( create: (context) => ExpenseBloc(), ), BlocProvider( create: (context) => NfcBloc(), ), BlocProvider( create: (context) => RefuelBloc(), ), BlocProvider( create: (context) => ObservationBloc(), ), BlocProvider( create: (context) => ValuesBloc(), ), BlocProvider( create: (context) => ManageUsersBloc(), ), ], child: MaterialApp( navigatorKey: navigatorKey, localizationsDelegates: const [ ...GlobalMaterialLocalizations.delegates, GlobalWidgetsLocalizations.delegate, // Other localization delegates if needed ], supportedLocales: const [ Locale('pt', 'BR'), // 这里假设你用的是葡萄牙语巴西地区,可根据实际调整 ], // 这里应该还有你的路由配置,比如initialRoute或者onGenerateRoute ), ); } }
我自己初步想到的几个排查方向,也想和大家讨论下
- AuthOrAppBloc的状态流转问题:会不会是
AuthOrAppInitialEvent触发后,Bloc重复发射了"已认证"状态,导致路由被两次导航到首页?可以在Bloc的mapEventToState里加打印,看状态发射了几次。 - TripBloc的初始化时机:我在
MultiBlocProvider里直接给TripBloc绑定了TripInitialEvent,会不会在Web环境下,因为Widget树的重建,这个Bloc被初始化了两次?可以给TripBloc的构造函数加打印,看实例化了几次。 - 路由跳转的逻辑问题:
authOrApp路由的判断逻辑里,是不是用了push而不是pushReplacement?或者有没有在认证状态变化时,重复触发了路由跳转? - Web环境的特殊生命周期:Flutter Web在初始化时,有没有可能因为浏览器的渲染机制,导致整个Widget树被重建了两次?可以在首页的
initState里加打印,看执行了几次。
相关产品推荐
相关产品推荐

