Home > Mobile >  Unhandled Exception: No ScaffoldMessenger widget found
Unhandled Exception: No ScaffoldMessenger widget found

Time:01-15

I'm attempting to enable auto-login by obtaining a token saved in the local mobile instance. I'm encountering this error. I'm using Provider for state management. In my main file , I want to retrieve my token to check whether user has been logged in or not. What i'm, doing wrong ?

My Error

E/flutter ( 6547): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: No ScaffoldMessenger widget found.
E/flutter ( 6547): MyApp widgets require a ScaffoldMessenger widget ancestor.
E/flutter ( 6547): The specific widget that could not find a ScaffoldMessenger ancestor was:
E/flutter ( 6547):   MyApp
E/flutter ( 6547): The ancestors of this widget were:
E/flutter ( 6547):   _InheritedProviderScope<UserProvider?>
E/flutter ( 6547):   ChangeNotifierProvider<UserProvider>
E/flutter ( 6547):   _NestedHook
E/flutter ( 6547):   MultiProvider
E/flutter ( 6547):   [root]
E/flutter ( 6547): Typically, the ScaffoldMessenger widget is introduced by the MaterialApp at the top of your application widget tree.

Main.dart file

void main() {
  runApp(MultiProvider(
      providers: [ChangeNotifierProvider(create: (context) => UserProvider())],
      child: const MyApp()));
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}):super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final AuthService authService = AuthService();
  @override
  void initState() {
    // TODO: implement initState
    authService.getUserData(context);
    super.initState();
  }

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ShopOne',
      theme: ThemeData(
        scaffoldBackgroundColor: GlobalVariables.backgroundColor,
        textTheme: Theme.of(context)
            .textTheme
            .apply(bodyColor: Colors.white, displayColor: Colors.white),

        colorScheme:
            const ColorScheme.light(primary: GlobalVariables.secondaryColor),
        appBarTheme: const AppBarTheme(
            elevation: 0, iconTheme: IconThemeData(color: Colors.white)),
        //
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      onGenerateRoute: ((settings) => generateRoute(settings)),
      home: Provider.of<UserProvider>(context).user.token.isNotEmpty
                  ? const HomeScreen()
                  : const AuthScreen()
    );
    if (Provider.of<UserProvider>(context).user.token.isNotEmpty) {
      print('true');
    } else {
      print('false');
      ;
    }
  }
}

get user function

  void getUserData(
    BuildContext context,
  ) async {
    try {
      
      SharedPreferences prefs = await SharedPreferences.getInstance();
      String? token = prefs.getString("auth-token");
      if (token == null) {
        prefs.setString('auth-token', '');
      }

      var tokenRes = await http.post(Uri.parse('$uri//tokenisvalid'),
          headers: <String, String>{
            'Content-Type': 'application/json;charset=UTF-8',
            'auth-token': token!
          });
      print('tokenres working 1');

      var response = jsonDecode(tokenRes.body);
      if (response == true) {
        http.Response userRes = await http.get(Uri.parse('$uri/'),
            headers: <String, String>{
              'Content-type': 'application/json;charset=UTF-8',
              'auth-token': token
            });
        print('tokenres working 2');

        var userProvider = Provider.of<UserProvider>(context, listen: false);
        userProvider.setUser(userRes.body);
      }
    } catch (e) {
      showSnackBar(context, e.toString());
    }
  }

CodePudding user response:

This happened because the context that you used in showSnackBar, doesn't belongs to any Scaffold, you need to separate the MaterialApp's home to new StatefulWidget class like this:

class ScreenManager extends StatefulWidget {
  const ScreenManager({Key? key}) : super(key: key);

  @override
  State<ScreenManager> createState() => _ScreenManagerState();
}

class _ScreenManagerState extends State<ScreenManager> {
  @override
  void initState() {
    // TODO: implement initState
    authService.getUserData(context);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Provider.of<UserProvider>(context).user.token.isNotEmpty
          ? const HomeScreen()
          : const AuthScreen(),
    );
  }

  void getUserData(BuildContext context) async {
   

    try {

      ...

    } catch (e) {
      WidgetsBinding.instance.addPostFrameCallback((_) {
         showSnackBar(context, e.toString());
      });
    }
  }
}

then use it like this:

home: ScreenManager();

Note: don't forget to remove authService.getUserData(context) from _MyAppState's initState.

  • Related