Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Persist Provider data across multiple pages not working

I'm using Provider in my flutter app, and when I go to a new page, the data provided to the Provider at page 1 is not accessible in page 2.

The way I understood the way Provider works, was that there is a central place where one stores all the data, and one can access that data anywhere in the application. So in my application, which is shown below, ToDoListManager is the place where all the data is stored. And if I set the data in Page 1, then I will be able to access that data in Page 2, and vice versa.

If this is not correct, then what part is wrong? And why isn't it working in my application?

Here's the code

Page 1

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      builder: (context) => ToDoListManager(),
      child: Scaffold(
        appBar: AppBar(
          title: Text('Cool Project'),
        ),
        body:e ToDoList(),
      ),
    );
  }
}

class ToDoList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final toDoListManager = Provider.of<ToDoListManager>(context);

    return ListView.builder(
      itemCount: toDoListManager.toDoList.length,
      itemBuilder: (context, index) {
        return GestureDetector(
          onTap: () {
            Navigator.push(context,
                MaterialPageRoute(builder: (context) => Details(index)));
          },
          child: Text(toDoListManager.toDoList[index]),
        );
      },
    );
  }
}

Page 2

class Details extends StatelessWidget {
  final int index;

  Details(this.index);

  @override
  build(BuildContext context) {
    return ChangeNotifierProvider(
      builder: (context) => ToDoListManager(),
      child: Scaffold(
          appBar: AppBar(
            title: Text('Details Bro'),
          ),
          body: AppBody(index)),
    );
  }
}

class AppBody extends StatelessWidget {
  final int index;

  AppBody(this.index);

  @override
  Widget build(BuildContext context) {
    final toDoListManager = Provider.of<ToDoListManager>(context);
    print(toDoListManager.toDoList);

    return Text(toDoListManager.toDoList[1]);
  }
}

ToDoListProvider

class ToDoListManager with ChangeNotifier {
  List<String> _toDoList = ['yo', 'bro'];

  List<String> get toDoList => _toDoList;

  set toDoList(List<String> newToDoList) {
    _toDoList = newToDoList;
    notifyListeners();
  }
}
like image 958
Jessica Avatar asked Sep 12 '19 16:09

Jessica


1 Answers

You have 2 options:

  1. Place your ChangeNotifierProvider above your MaterialApp so that is accesible from any of you Navigator routes.

  2. Keep your Home widget as is but when pushing the new widget with the Navigator provide the original Manager.

onTap: () {
    Navigator.push(
        context,
        MaterialPageRoute(
            builder: (context) {
                return Provider<ToDoListManager>.value(
                    value: toDoListManager,
                    child: Details(index),
                );
            },
        ),
    );
},

With both approaches you don't need to create a new ChangeNotifierProvider in your details screen.

like image 70
Martyns Avatar answered Dec 05 '22 12:12

Martyns