Search code examples
flutterdartflutter-futurebuilder

Why FutureBuilder re-build every time?


I'm working with FutureBuilder and I initialize _future in InitState as mentioned here. Despite this, FutureBuilder re-build itself every time I switch page with the BottomNavigationBar.

Code Sample:

class _HomeViewState extends State<HomeView> {

  late final Future<List<DocumentSnapshot<Object?>>> _futureSerieA;



  @override
  void initState() {

    super.initState();
    _futureSerieA = getScheduled("Serie A");

  }

  @override
  Widget build(BuildContext context) {
    return SizedBox.expand(
      child: SingleChildScrollView(
        child: Column(
          children: [


            Padding(
              padding: const EdgeInsets.fromLTRB(0,0,0,0),
              child: Container(
                decoration: const BoxDecoration(

                  border: Border(

                    bottom: BorderSide(color: Colors.transparent)
                  )
                ),
                child: Theme(
                  data: Theme.of(context).copyWith(dividerColor: Colors.transparent),
                  child: FutureBuilder(
                    future: _futureSerieA,
                    builder: (context, AsyncSnapshot<List<DocumentSnapshot>> snapshot) {

                      if (snapshot.hasData) {
                        List<String> scheduled = [];

                        for (var DOC in snapshot.data!) {
                          scheduled.add(DOC.id);
                        }
                        return ...

How could I disable FutureBuilder re-build when browsing between pages of BottomNavigationBar?

BottomNavBar:

class _LoggedHandleState extends State<LoggedHandle> {

 
  );
  double height = AppBar().preferredSize.height;

  int _selectedPage = 1;
  final _pageOptions = [
    const BetView(),
    const HomeView(),
    const UserView()
  ];




  @override
  Widget build(BuildContext context) {
    return Scaffold(

      ...
      ),
    

      bottomNavigationBar: BottomNavigationBar(
          unselectedItemColor: Colors.white60,
          backgroundColor: Colors.red,
          selectedItemColor: Colors.white,
          currentIndex: _selectedPage,
          onTap: (int index) {
            setState(() {
              _selectedPage = index;
            });
          },
          items: const <BottomNavigationBarItem>[
            BottomNavigationBarItem(
              icon: Icon(Icons.receipt),
              label: 'Schedina',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.home),
              label: 'Home',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.account_circle),
              label: 'Account',
            ),
          ]),

      body: _pageOptions[_selectedPage],
    );
  }

 
}


Solution

  • When browsing between pages of bottom navigation bar, your state is not maintained. This behaviour causes the widget to rebuild every time.

    You can use Indexed Stack https://api.flutter.dev/flutter/widgets/IndexedStack-class.html

      @override
          Widget build(BuildContext context) {
            return Scaffold(
              bottomNavigationBar: BottomNavigationBar(
                onTap: (index) {
                  setState(() {
                    current_tab = index;
                  });
                },
                currentIndex: current_tab,
                items: [
                  BottomNavigationBarItem(
                    ...
                  ),
                  BottomNavigationBarItem(
                    ...
                  ),
                ],
              ),
              body: IndexedStack(
                children: <Widget>[
                  PageOne(),
                  PageTwo(),
                ],
                index: current_tab,
              ),
            );
          }
    

    Although this is the best solution, it will load all your widgets once the IndexedStack is loaded. I found a Lazy Loading Indexed Stack util to load your widgets when and only the first time they are created https://github.com/okaryo/lazy_load_indexed_stack