Flutter:应用程序在热重载后不断回到初始路线

Posted

技术标签:

【中文标题】Flutter:应用程序在热重载后不断回到初始路线【英文标题】:Flutter: App keeps going back to initial route after hot reload 【发布时间】:2021-03-18 17:47:35 【问题描述】:

我刚刚根据迁移指南https://firebase.flutter.dev/docs/migration 将 FireBase 插件升级到最新版本,并开始注意到每当我进行热重载时,我的应用程序都会进行热重启并返回初始路线。首先我认为这可能是 android Studio 的问题,所以我也尝试了命令提示符和 VS 代码,但结果相同。我已经搜索了与该主题相关的旧 *** 问题,但找不到任何可以解决问题的东西。 我在下面复制我的代码。 PS:我对 Flutter 很陌生,这是我在 *** 中遇到的第一个问题。

非常感谢任何帮助。 编辑:刚刚调试它,发现执行热重载时它会回到 runApp(...) 。

main.dart

void main() async 
  String authMethod;
  WidgetsFlutterBinding.ensureInitialized();
  SharedPreferenceService localStorage = SharedPreferenceService();
  authMethod = await localStorage.getAuthMode();
  print("Authentication Mode $authMethod");
  setupLocator();


  runApp(
    DevicePreview(
        enabled: false,//kReleaseMode,
        builder: (context)=>AppInitialization())
      );

AppInitialization.dart

class AppInitialization extends StatelessWidget 
  final Future<FirebaseApp> _initialization = Firebase.initializeApp();
  @override
  Widget build(BuildContext context) 
    return FutureBuilder(
      future: _initialization,
        builder: (context, snapshot) 
        if (snapshot.hasError) 
          return Center(
            child: Container(
              child: Text('Unable to Initialize FireBase'),
            ),
          );
        
        if (snapshot.connectionState == ConnectionState.done) 
          print("======= F I R E  B A S E  A P P ========");
          return LocalGroceryOnline();
        
        return Center(
          child: SizedBox(
            height: 40,
            width: 40,
            child: CircularProgressIndicator(
                strokeWidth: 2.0,
                valueColor: AlwaysStoppedAnimation<Color>(Colors.redAccent, )),
          ),
        );

        );
  

LocalGroceryOnline.dart

class LocalGroceryOnline extends StatelessWidget 
  final GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>();
  @override
  Widget build(BuildContext context)     
    return MultiProvider  (
      providers: [
        Provider<FirebaseAuthService>(create: (_) => FirebaseAuthService()),
        Provider<SignInHelperService>(create: (_) => SignInHelperService()),
        Provider<SharedPreferenceService>(create: (_) => SharedPreferenceService()),
        ChangeNotifierProvider<CartModel>(create: (_) => CartModel()),
        ChangeNotifierProvider<UserModel>(create: (_) => UserModel()),
        ChangeNotifierProvider<ProductModel>(create: (_) => ProductModel()),
        ChangeNotifierProvider<cat.Category>(create: (_) => cat.Category()),
        ChangeNotifierProvider<AppSetting>(create: (_) => AppSetting()),
        ChangeNotifierProvider<ValueNotifier<bool>>(create: (_) => ValueNotifier<bool>(false),),
        ChangeNotifierProvider<ValueNotifier<int>>(create: (_) => ValueNotifier<int>(0),)

      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Online Local Grocery',
        locale: DevicePreview.of(context).locale,
        builder: DevicePreview.appBuilder,
        theme: ThemeData(
          primaryColor: Colors.white,
          fontFamily: 'Montserrat',
          appBarTheme: AppBarTheme(elevation: 0.0), //This is important

        ),
        initialRoute: AuthWidget.id,
        navigatorKey: navigatorKey,

        onGenerateRoute: RouteGenerator.generateRoute,
        //onGenerateInitialRoutes: InitialRouteGenerator.generateRoute(),
      )
          ,
    );
  

RouteGenerator.dart

class RouteGenerator 
  static Route<dynamic> generateRoute(RouteSettings settings) 
    final args = settings.arguments;

    switch (settings.name) 
      case AuthWidget.id:
        return MaterialPageRoute(builder: (_) => AuthWidget());

      case SignUpSelectionScreen.id:
        return MaterialPageRoute(builder: (_) => SignUpSelectionScreen());
      case SignupForm.id:
        return MaterialPageRoute(builder: (_) => SignupForm());
      case LoginView.id:
        return MaterialPageRoute(builder: (_) => LoginView());
      case HomePage.id:
        return MaterialPageRoute(builder: (_) => HomePage());
      case MainPage.id:
        if (args.runtimeType == MainCategory) 
          return MaterialPageRoute(
              builder: (_) => MainPage(
                mainCategory: args,
              ));
        
        return _errorRoute();
      case ProductDetail.id:
        if (args.runtimeType == SelectedProductArguments) 
          return MaterialPageRoute(
              builder: (_) => ProductDetail(
                    selectedProductArguments: args,
                  ));
        
        return _errorRoute();
      case CheckOutScreen.id:
        return MaterialPageRoute(builder: (_) => CheckOutScreen());
      case Admin.id:
        return MaterialPageRoute(builder: (_) => Admin());
      case ScrapBoard.id:
        return MaterialPageRoute(builder: (_) => ScrapBoard());
      case ProductAdminView.id:
        return MaterialPageRoute(builder: (_) => ProductAdminView());
      case DeliveryAddressView.id:
        return MaterialPageRoute(builder: (_) => DeliveryAddressView());
      case PaymentView.id:
        return MaterialPageRoute(builder: (_) => PaymentView());
      case OrderProcessingView.id:
        return MaterialPageRoute(builder: (_) => OrderProcessingView());
      case MyOrdersView.id:
        return MaterialPageRoute(builder: (_) => MyOrdersView());
      case MyOrderDetails.id:
        if (args.runtimeType == Order) 
        return MaterialPageRoute(builder: (_) => MyOrderDetails(
          order: args,
        )
         );
        
        return _errorRoute();

      default:
        // If there is no such named route in the switch statement, e.g. /third
        return _errorRoute();
    
  

  static Route<dynamic> _errorRoute() 
    return MaterialPageRoute(builder: (_) 
      return Scaffold(
        appBar: AppBar(
          title: Text('Error'),
        ),
        body: Center(
          child: Text('ERROR'),
        ),
      );
    );
  


class InitialRouteGenerator 
  static Route<dynamic> generateRoute(RouteSettings settings) 
    bool _firstTimeAppUsed;
    final localStorage = new SharedPreferenceService();
    localStorage.isFirstTimeAppUsed().then((bool value) 
      if (value == true) 
        _firstTimeAppUsed = true;
      
    );
    if (_firstTimeAppUsed) 
      return MaterialPageRoute(builder: (_) => SignUpSelectionScreen());
    
    return MaterialPageRoute(builder: (_) => HomePage());
  

AuthWidget.dart

class AuthWidget extends StatelessWidget 
  static const id = "auth_widget";

  @override
  Widget build(BuildContext context) 
    print("Auth Widget...");
    final authService =
        Provider.of<FirebaseAuthService>(context, listen: false);
    final userModel = Provider.of<UserModel>(context, listen: false);
    final signInHelperService = Provider.of<SignInHelperService>(context, listen: false);

    return StreamBuilder(
        stream: authService.onAuthStateChanged,
        builder: (context, snapshot) 
          if (snapshot.connectionState == ConnectionState.active) 
            print ("INSIDE AUTH WIDGET");
            final user = snapshot.data;
            if (user != null) 
              print("$user.uid $user.userName $user.photoUrl");
              userModel.user = user;
              return StreamBuilder(
                  stream: FirebaseFirestore.instance
                      .collection('users')
                      .doc(user.uid)
                      .get().asStream(),
                  builder: (context, userSnapshot) 
                    if (userSnapshot.hasData && snapshot.connectionState == ConnectionState.active) 
                      final userDocument = userSnapshot.data;
                      if (userDocument != null) 
                        print("------ Data Found -------");
                        AppUser user = AppUser.fromMap(userDocument);
                        //bool signUpComplete = userDocument["signUpComplete"];
                        bool signUpComplete = user.signUpComplete;
                        if (signUpComplete == null) signUpComplete = false;
                        if (!signUpComplete) 
                          print("userModel.user UID $userModel.user.uid");
                          return SignupForm();
                         else 
                          AppUser user2 = AppUser.fromMap(userDocument);
                          userModel.user = user2;
                          print('User Level ..... $userModel.user.userLevel');
                          signInHelperService.getAndUpdateDeviceToken(user2);

                          return HomePage(); //MainPage();
                        
                      
                    
                    return emptyScaffoldWithProgress();
                  );
            
            return SignUpSelectionScreen();
          
          return emptyScaffoldWithProgress();
        );
  

  Scaffold emptyScaffoldWithProgress() 
    return Scaffold(
      body: Center(
        child: SizedBox(
          height: 90,
          width: 90,
          child: CircularProgressIndicator(
              strokeWidth: 5.0,
              valueColor: AlwaysStoppedAnimation<Color>(Colors.redAccent)),
        ),
      ),
    );
  

颤振医生-v

[√] Flutter (Channel stable, 1.22.4, on Microsoft Windows [Version 10.0.19041.630], locale en-US)
    • Flutter version 1.22.4 at C:\src\flutter
    • Framework revision 1aafb3a8b9 (3 weeks ago), 2020-11-13 09:59:28 -0800
    • Engine revision 2c956a31c0
    • Dart version 2.10.4


[√] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
    • Android SDK at C:\Users\Jamal\AppData\Local\Android\sdk
    • Platform android-29, build-tools 29.0.3
    • Java binary at: C:\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
    • All Android licenses accepted.

[√] Android Studio (version 4.0)
    • Android Studio at C:\Android\Android Studio
    • Flutter plugin version 47.1.2
    • Dart plugin version 193.7361
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)

[√] VS Code (version 1.51.1)
    • VS Code at C:\Users\Jamal\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.17.0

[√] Connected device (1 available)
    • Android SDK built for x86 (mobile) • emulator-5554 • android-x86 • Android 10 (API 29) (emulator)

• No issues found!

【问题讨论】:

找到罪魁祸首,是 DevicePreview 导致在热重载时执行 runApp。我不知道为什么现在它工作正常。我现在已经删除了。希望它可以帮助某人。 【参考方案1】:

我找到了罪魁祸首,是 DevicePreview 导致在热重载时执行 runApp。我不知道为什么现在它工作正常。我现在已经删除了。

【讨论】:

以上是关于Flutter:应用程序在热重载后不断回到初始路线的主要内容,如果未能解决你的问题,请参考以下文章

颤振:使用提供程序时,状态在热重载时丢失

仅在热重新加载后才加载我的值

使用提供程序包 FLUTTER 关闭应用程序后保存状态

Flutter:未处理的异常:无法加载资产

标记不会在 Flutter 中显示

颤振有状态的小部件在热重载和 pushNamed 之后丢失数据