Home > Software design >  Provider not passed to child
Provider not passed to child

Time:11-11

I have searched far and wide, i have studied the provider package but i still can't figure out why the children of the Material app dont have access to it's provider.

I have created a class to pass retreive the user preferences and create a ThemeData object. Then i create the MaterialApp using a ChangeNotifierProvider and the children don't have access to the ThemeViewModel class.

main.dart

void main() {
  runApp(MyApp());
}

class MainBuilder extends StatelessWidget {
  const MainBuilder({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<ThemeViewModel>(
      create: (_) {
        return ThemeViewModel();
      },
      child: Consumer<ThemeViewModel>(
        builder: (context, ThemeViewModel themeNotifier, child) {
          themeViewModel = themeNotifier.;
          return MaterialApp(
            title: StringConstants.appTitle,
            theme: themeNotifier.themeData,
            home: Login(user: UserModel(username: 'user', password: 'mona')),
            localizationsDelegates: const [
              AppLocalizations.delegate,
              GlobalMaterialLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate,
              GlobalCupertinoLocalizations.delegate,
            ],
            supportedLocales: const [
              Locale('en', ''),
              Locale('it', ''),
            ],
            localeListResolutionCallback: (locales, supportedLocales) {
              for (Locale locale in locales!) {
                for (Locale local in supportedLocales) {
                  if (locale.languageCode == local.languageCode) return locale;
                }
              }
              return const Locale('en', '');
            },
          );
        },
      ),
    );
  }
}

Login class

class Login extends StatefulWidget {
  final UserModel user;
  const Login({ required this.user, Key? key}) : super(key: key);

  @override
  State<Login> createState() => _LoginState();
}

class _LoginState extends State<Login> with SingleTickerProviderStateMixin {

  final _formKey = GlobalKey<FormState>();
  late TextEditingController _userNameController;
  late TextEditingController _passwordController;
  late Animation<Offset> _animation;
  late Tween<Offset> _tween;
  late AnimationController _animationController;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(vsync: this, duration: const Duration(milliseconds: 1200))..repeat(reverse: true);
    _tween = Tween(begin: Offset.zero, end: Offset(0, 0.08));
    _animation = _tween.animate(CurvedAnimation(parent: _animationController, curve: Curves.easeInOut))..addListener(() {setState(() {});});
  }

  @override
  void dispose() {
    _userNameController.dispose();
    _passwordController.dispose();
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        margin: const EdgeInsets.all(10),
        child: SingleChildScrollView (
          child: Column(
            children: [
              _animationWidget(),
              _loginForm(),
              Consumer<ThemeViewModel>(
                builder: (context, ThemeViewModel theme, child) {
                  return Text(theme.themeData.toString());
                },
              )
            ],
          ),
        ),
      ),
    );
  }
}

If you need anything else ill gladly provide it because i banged my head long enough on this problem.

CodePudding user response:

I had the same issue yesterday and I solved modifying my main this way:

void main() => runApp(ChangeNotifierProvider(
   create: (BuildContext context) => YourProvider(),
   child: MyApp()));

CodePudding user response:

Use the MultiProvider in main.dart to make the scope of the provider for the entire app. It will solve your problem.

main.dart:

void main() {
  runApp(MyApp());
}

class MainBuilder extends StatelessWidget {
  const MainBuilder({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return  MultiProvider(
      providers: [
        
        ChangeNotifierProvider<ThemeViewModel>(create: (_) => ThemeViewModel()),
       
        
      ],
      child:
      Consumer<ThemeViewModel>(
        builder: (context,  themeNotifier, child) {
          themeViewModel = themeNotifier.;
          return MaterialApp(
            title: StringConstants.appTitle,
            theme: themeNotifier.themeData,
            home: Login(user: UserModel(username: 'user', password: 'mona')),
            localizationsDelegates: const [
              AppLocalizations.delegate,
              GlobalMaterialLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate,
              GlobalCupertinoLocalizations.delegate,
            ],
            supportedLocales: const [
              Locale('en', ''),
              Locale('it', ''),
            ],
            localeListResolutionCallback: (locales, supportedLocales) {
              for (Locale locale in locales!) {
                for (Locale local in supportedLocales) {
                  if (locale.languageCode == local.languageCode) return locale;
                }
              }
              return const Locale('en', '');
            },
          );
        },
      ),
    );
  }
}

  • Related