Search code examples
flutterflutter-providerflutter-navigation

I can't access newly created provider on the next screen/route


Main() - The MyApp only contains the ListItemWidget

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

List Item Screen - Is creating provider for every item allowed? I wanted to pass the item index as an argument for the provider.

    class ListItemScreen extends StatelessWidget {
      const ListItemScreen({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        
        final mainProvider = Provider.of<MainProvider>(context);
        
        return  Scaffold(
          floatingActionButton: FloatingActionButton(
            onPressed: () {},
          ),
          body: ListView.builder(
            itemCount: mainProvider.getItems().length,
            itemBuilder: (context, index) {
              final item = mainProvider.getItems()[index];
              return ChangeNotifierProvider(
                create: (_) => SecondProvider(secondItem: item),
                builder: (context, child){
                  return ListTile(
                    leading: IconButton( // This onPressed can access the provider
                      onPressed: () { context.read<SecondProvider>().test();}, 
                      icon: Icon(Icons.add),
                    ),
                    onTap: () { //When I press this and go to second it can't access it
                      Navigator.push(
                        context,
                        MaterialPageRoute(
                          builder: (context) => SecondScreen()));
                    },
                    title: Text('TITLE TEST: ${mainProvider.getItems()[0].title}'),
                  );},);},),);}
    }

SecondScreen

    class SecondScreen extends StatelessWidget {
      const SecondScreen({Key? key}) : super(key: key);
    
      //It can't find the Provider (SecondProvder)
      @override
      Widget build(BuildContext context) {
        final secondProvider = Provider.of<SecondProvider>(context);
        return Scaffold(
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              secondProvider.changeTitle();
            },),
          body: Center(
              child: Text(
                'Show Title: ${secondProvider.getTitle()}'
              ),));
      }
    }

SecondProvider

    class SecondProvider extends ChangeNotifier{
    
      MyItem _item;
    
      SecondProvider({required MyItem item}) : _item = item;

      void test(){
          print('Test print ${_item.title}');
      }
      void changeTitle(){
          _title = 'Test Title';
          notifyListeners();
      }
    
      String getTitle() => _item.title;
    
    }

Basically I want the 'item' model passed to my provider so that I can access it on the next screen and notify the view for changes, the provider will act like a view model.


Solution

  • You need to pass your SecondProvider provider

    final _provider = Provider.of<SecondProvider>(context);
    
      Navigator.push(
        context,
        MaterialPageRoute(
            builder: (context) => Provider.value(
                value: _provider, child: SecondScreen())),
      );