Updating a page every time I revisit the page in BottomNavigationbar

Issue

In my app the user is able to store favorite items on a different page in the bottom navigation bar. My problem is that the page does not refresh properly. If you add a favorite it gets displayed only when restarting the app.
If the favorites page is in the same widget hierarchy of the respective bottomnavitem the function works fine.

https://pastebin.com/nZ2jrLqK

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

  @override
  _FavoritesState createState() => _FavoritesState();
}

class _FavoritesState extends State<Favorites> {
  // ignore: prefer_typing_uninitialized_variables
  var database;
  List<Mechanism> people = <Mechanism>[];

  Future initDb() async {
    database = await openDatabase(
      join(await getDatabasesPath(), 'person_database.db'),
      onCreate: (db, version) {
        return db.execute(
          "CREATE TABLE person(id INTEGER PRIMARY KEY,  name TEXT, height TEXT, mass TEXT, hair_color TEXT, skin_color TEXT, eye_color TEXT, birth_year TEXT, gender TEXT)",
        );
      },
      version: 1,
    );

    getPeople().then((value) {
      setState(() {
        people = value;
      });
    });
  }

  Future<List<Mechanism>> getPeople() async {
    final Database db = await database;

    final List<Map<String, dynamic>> maps = await db.query('person');
    return List.generate(maps.length, (i) {
      return Mechanism(
        id: maps[i]['id'],
        name: maps[i]['name'] as String,
      );
    });
  }


  @override
  void initState() {
    super.initState();
    initDb();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: backGround,
      appBar: AppBar(
        backgroundColor: appbarColor,
        title: const Text("Favorites"),
      ),
      body: ListView.builder(
          itemCount: people.length,
          itemBuilder: (context, index) {
            var person = people[index];
            return ListTile(
              title: Text(
                person.name,
                style: const TextStyle(color: titleColor),
              ),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                      builder: (context) =>
                          MechanismDtl(mechanism: person, id: index)),
                );
              },
            );
          }),
    );
  }
}

Edit: page where the user can store the items

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

  @override
  _MarkFavsState createState() => _MarkFavsState();
}

class _MarkFavsState extends State<MarkFavs> {
  TextEditingController searchController = TextEditingController();
  List<People> shownList = <People>[
    People(name: 'Test', id: 1),
    People(name: 'Test2', id: 2),
    People(name: 'Test3', id: 3)
  ];
  List<People> initialData = <People>[
    People(name: 'Test', id: 1),
    People(name: 'Test2', id: 2),
    People(name: 'Test3', id: 3)
  ];

  void queryPeople(String queryString) {
    if (kDebugMode) {
      print("queryString = $queryString");
    }

    setState(() {
      shownList = initialData.where((string) {
        if (string.name.toLowerCase().contains(queryString.toLowerCase())) {
          return true;
        } else {
          return false;
        }
      }).toList();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: backGround,
      appBar: AppBar(
        backgroundColor: appbarColor,
        title: const Text('Detail'),
      ),
      body: Column(
        children: <Widget>[
          TextButton.icon(
            label: const Text('Favorites'),
            icon: const Icon(
              Icons.storage,
              color: titleColor,
            ),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => const Favorites()),
              );
            },
          ),
          Expanded(
            child: PeopleList(
              people: shownList,
            ),
          ),
        ],
      ),
    );
  }
}

class PeopleList extends StatelessWidget {
  final List<People> people;

  const PeopleList({Key key, this.people}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: people.length,
      itemBuilder: (context, index) {
        var person = people[index];
        var name = person.name;
        return ListTile(
          title: Text(
            name,
            style: const TextStyle(color: titleColor),
          ),
          onTap: () {
            person.id = index;
            Navigator.push(
              context,
              MaterialPageRoute(
                  builder: (context) =>
                      MechanismDtl(mechanism: person, id: index)),
            );
          },
        );
      },
    );
  }
}

Solution

Maybe not the most efficient method, but if you provide a passback to the Favourites class from the parent widget you can call a setState in the parent widget (assuming the parent widget reloads the database).

    class Favorites extends StatefulWidget {
  const Favorites({Key? key, this.passback}) : super(key: key);
  final Function passback;

  @override
  _FavoritesState createState() => _FavoritesState();
}

Then the passback would look like:

passback() {
   setState(){
     //Reload db
   }
}

And pass it into Favourite (does not work with named routes AFAIK)

  Navigator.push(
        context,
        MaterialPageRoute(builder: (context) => Favourites(passback: passback)),
 );

Then just call passback when the user adds the item to their favourites.

Answered By – shed

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published