'Navigating to another screen gets slower and slower each time i repeat click, go back, click, go back

I have a Navigator.push and MaterialPageRoute() to navigate to another screen. But navigation to other screens gets slower and slower becuase in my initState() i have a method which initializes the json data which i show each time i navigate to another screen. The json data is big and i only use one file with big json data which has objects and each object is shown i different screens. In my usecase i have to use one file with big json data.

In my initState() i initialize the data i grabbed with the method setTestData() and inside this method i set the data inside an object:

  late Map<String, dynamic> grabbedData = {};

  setTestData() async {
    await TestData()
        .getTestData()
        .then((result) => setState(() => grabbedData = result));
  }

  @override
  initState() {
    setTestData();
    super.initState();
  }

In my view i can for example navigate to another screen and then show different objects inside the same object json i grabbed in setTestData(). I only use one view called AppView() to show different screen so when i navigate for example from screen A to B, both A and B screen are shown with AppView() widget. This is necessary for my use case which is irrelevant for this question.

This is the navigation which i use to load another screen and which technacly runs initState() from AppView() again because the previous route is also AppView():

 Navigator.push(
                                                context,
                                                MaterialPageRoute(
                                                    maintainState: false,
                                                    builder: (_) => AppView(
                                                          selectedMenuItems:
                                                              grabbedData['data']
                                                                      ['views'][
                                                                  widget.selectedMenuItems[
                                                                          index]
                                                                      [
                                                                      'content']],
                                                        )));

But the problem is that each time i navigate to AppView() and click back on my phone to show previous data from AppView() and navigate again, it re-initializes the state and so the proces is slowed after i repeat it a couple of times. How do i solve this problem?



Solution 1:[1]

Better to use Provider package for this task. Provider does not rebuild the widget rather it only updates the state of the widget so it is faster. Then, you can get your data or data stream only once at the beginning of your app or a particular screen. No need to generate data each time. Also, provider automatically disposes data when the screen is closed. It is recommended by flutter team as well and an awesome package. For more example, check some YouTube videos. For your particular problem, I think it is better to use provider.value. Check the references and hopefully later on you will understand what is a provider.value object.

If you are generating new data every time then you need to set your provider.value each time where you are using Navigator.push, otherwise if you do not use your provider at the beginning of your app at MaterialApp section then after the push the provider won't be available.

As an example, to add provider inside a push please follow the following code snippet:

Navigator.push(context,
    MaterialPageRoute(builder: ((context) {
    
    return StreamProvider<User>.value(
        initialData: initialUserData,
        value: userDataStream,
        child: const UpdateUser(),
    );
})));

Next, access the value in the UpdateUser page like this:

final user = Provider.of<User>(context);

If you are not using any data stream then just try the normal ChangeNotifierProvider and get the value from the Consumer. Try some youtube tutorials and you will love it.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1