bottomNavigationBar keeps rebuilding multiple times when calling Navigator.pushNamed inside tab

1,129 views
Skip to first unread message

Andrew

unread,
May 30, 2018, 7:54:41 AM5/30/18
to Flutter Dev

I have a problem with the structure/design of Flutter project.


At the moment structure looks like this:


Homepage with bottomNavigationBar with multiple tabs, each tab is StatefulWidget and contains some heavy processing (remote API calls and data display).

In case I call Navigator.pushNamed from inside of any tab, following happens:

  1. All tabs are being rebuild in the background (making API calls, etc).
  2. New page opens normally.
  3. When I press back button, page closes and all tabs are rebuild again.

So in total everything (each tab) is rebuilt 2 times just to open external navigator page.


Is this some sort of bug? Completely not understandable why it's fully rebuilding bottomNavigationBar just before pushing new route.


How it should work:

  1. When I call Navigator.pushNamed from inside the tab, new page should be open and all bottomNavigationBar tabs should not be rebuild and stay in unchanged state.
  2. When I press back, page should close and user return to the same state of bottomNavigationBar and it's tabs, no rebuilding at all.

Is this possible to achieve? Maybe some other ways to get this result?


Here is the homepage code:


class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => new _HomePageState();
}

class _HomePageState extends State<HomePage> {


  int index = 0;

  final _tab1 = new tab1();   //StatefulWidget, api calls, heavy data processing
  final _tab2 = new tab2();   //StatefulWidget, api calls, heavy data processing


  @override
  Widget build(BuildContext context) {

    debugPrint('homepage loaded:'+index.toString());


    return new Scaffold(
      body: new Stack(
        children: <Widget>[

          new Offstage(
            offstage: index != 0,
            child: new TickerMode(
              enabled: index == 0,
              child: _tab1,
            ),
          ),
          new Offstage(
            offstage: index != 1,
            child: new TickerMode(
              enabled: index == 1,
              child: _tab2,   
            ),
          ),


        ],
      ),
      bottomNavigationBar: new BottomNavigationBar(
        currentIndex: index,
        type: BottomNavigationBarType.fixed,
        onTap: (int index) { setState((){ this.index = index; }); },
        items: <BottomNavigationBarItem>[
          new BottomNavigationBarItem(
            icon: new Icon(Icons.live_help),
            title: new Text("Tab1"),
          ),
          new BottomNavigationBarItem(
            icon: new Icon(Icons.favorite_border),
            title: new Text("Tab 2"),
          ),


        ],
      ),
    );
  }
}


Here is single tab code:

class tab1 extends StatefulWidget {



 
@override
  tab1State createState
() => new tab1State();
}


class tab1State extends State<tab1> {


 
@override
 
Widget build(BuildContext cntx) {


    debugPrint
('tab loaded');  //this gets called when Navigator.pushNamed called and when back button pressed

   
//some heave processing with http.get here...  
   
//...


   
return new Center(
        child
: new RaisedButton(
          onPressed
: () {

           
Navigator.pushNamed(context, '/some_other_page');


         
},
          child
: new Text('Open new page'),
       
));


 
}

}



Eugenio Tesio

unread,
May 30, 2018, 8:29:17 AM5/30/18
to Andrew, Flutter Dev
I think your problem can be solved by returning a Scaffold body dynamically; creating a function that return the Stack or the body in '/some_other_page' without changing the navigator bar widget.

--
You received this message because you are subscribed to the Google Groups "Flutter Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to flutter-dev...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
Eugenio Tesio
Zetus - Soluciones Empresariales
División Sistemas
(+549) 3564-15-599945
San Francisco - 2400
Pcia de Córdoba - Argentina



Andrew

unread,
May 30, 2018, 9:39:43 AM5/30/18
to Flutter Dev
not really sure what you mean. Do you have an example?

/some_other_page looks like this:


class SomeOtherPage extends StatelessWidget {
  @override


  Widget build(BuildContext context) {


    return new Scaffold(
     appBar: new AppBar(
        title: new Text("New page"),
      ),
      body: new Center(
        child:  new Text('completely new page without bottomNavigationBar'),
        ),

      ),

    );
  }

}


Eugenio Tesio

unread,
May 30, 2018, 9:58:32 AM5/30/18
to Andrew, Flutter Dev
Something like this:


class SomeOtherPage extends StatelessWidget {
  @override

  Widget dynamicBody() {
    if(some_condition) {
      return new Text('completely new page without bottomNavigationBar')
    } else {
      return new Stack(
        children: <Widget>[

          new Offstage(
            offstage: index != 0,
            child: new TickerMode(
              enabled: index == 0,
              child: _tab1,
            ),
          ),
          new Offstage(
            offstage: index != 1,
            child: new TickerMode(
              enabled: index == 1,
              child: _tab2,   
            ),
          ),


        ],
    }
  }

  Widget build(BuildContext context) {


    return new Scaffold(
     appBar: new AppBar(
        title: new Text("New page"),
      ),
      body: new Center(
        child: dynamicBody()
        ),

      ),

    );
  }
}

Andrew

unread,
May 30, 2018, 10:04:07 AM5/30/18
to Flutter Dev

thank you for suggestion, this is basically the workaround I'm using right now. Making each tab to contain multiple screens. However it feels as very ugly solution. So I thought maybe there is a proper way to make bottomNavigationBar work with Navigator.
Reply all
Reply to author
Forward
0 new messages