Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pages on Navigator stack rebuild when a new page is pushed #11655

Open
cornelius-tan opened this issue Aug 17, 2017 · 65 comments

Comments

@cornelius-tan
Copy link

commented Aug 17, 2017

Steps to Reproduce

Pages on Navigator stack rebuild when a new page is pushed onto the stack.
Suppose the pages were numbered numerically, in the order they are pushed onto the stack i.e. page 1 -> page 2 -> page 3. When we push Page 3, previous pages from page 1 to 2 rebuild as evident from the print statements. Is this a bug?

import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(id: 1),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.id}) : super(key: key);

  final int id;

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

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    print('Page ${widget.id} built!');
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.id.toString()),
      ),
      body: new Center(
        child: new RaisedButton(
          child: new Text('Open next page'),
          onPressed: () {
            Navigator.of(context).push(
              new MaterialPageRoute(
                builder: (_) => new MyHomePage(id: widget.id + 1),
                maintainState: true
              )
            );
          }
        )
      ),
    );
  }
}

Logs

When page 2 is pushed, the log outputs

I/flutter (21176): Page 2 built!
I/flutter (21176): Page 2 built!
I/flutter (21176): Page 1 built!

Expected:

I/flutter (21176): Page 2 built!  // only 

When page 3 is pushed, the log outputs

I/flutter (21176): Page 2 built!
I/flutter (21176): Page 3 built!
I/flutter (21176): Page 3 built!
I/flutter (21176): Page 2 built!
I/flutter (21176): Page 1 built!

Expected:

I/flutter (21176): Page 3 built!  // only 

Flutter Doctor

[√] Flutter (on Microsoft Windows [Version 10.0.15063], locale en-US, channel master)
    • Flutter at C:\Users\tzm\Downloads\flutter_sdk
    • Framework revision b156a0f054 (5 days ago), 2017-08-11 22:01:40 -0700
    • Engine revision fef7d827d6
    • Tools Dart version 1.25.0-dev.9.0

[√] Android toolchain - develop for Android devices (Android SDK 25.0.3)
    • Android SDK at C:\Users\tzm\AppData\Local\Android\sdk
    • Platform android-26, build-tools 25.0.3
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_112-release-b06)
@Kerego

This comment has been minimized.

Copy link

commented Nov 30, 2017

I have noticed this behavior but couldn't figure out what is the problem, can someone from the team comment on this?

@Hixie

This comment has been minimized.

Copy link
Contributor

commented Nov 30, 2017

This is working as intended. In general, you should assume that all widgets can rebuild at any time, that they don't is mostly just an optimisation.

In particular, routes will rebuild because their navigator state has changed so they might need to update how they draw back buttons and the like.

@Hixie Hixie added the f: routes label Mar 8, 2018
@lidroider

This comment has been minimized.

Copy link

commented Jul 6, 2018

@Hixie
I have same issue with @cornelius-tan
I understand that when navigator state has changed, routes will rebuild
But I follow the document of MaterialPageRoute, I found out maintainState = true to keep state of previous route.
So what is the "actual" meaning of maintainState and what is the state in maintainState?
Please give me your opinion
p/s: sorry for my English

@Hixie

This comment has been minimized.

Copy link
Contributor

commented Jul 13, 2018

maintainState controls whether the route's widgets and render objects are kept around or not. If you set it to false on a route, then when another route is pushed on top, the entire subtree is thrown away until that route is popped.

@zoechi zoechi added the framework label Jul 22, 2018
@lidroider

This comment has been minimized.

Copy link

commented Aug 8, 2018

@Hixie
Is there any way to prevent rebuild a widget when another route is pushed on top?
Ex: I have route /a -> Widget A, /b -> Widget B. When I push route /b on /a, Widget A is rebuilt and Widget B is built; when i pop /b, Widget A is rebuilt again.
I expect Widget A not to be rebuilt when i push and pop /b
Please help me
Thks

@Hixie

This comment has been minimized.

Copy link
Contributor

commented Aug 13, 2018

You should generally assume that every widget will be rebuild every frame, and design your build methods to be idempotent (i.e. running them multiple times should do nothing different than running them once), and fast (so that there's no problem with running them a lot). In practice we run build methods less often than that but you shouldn't rely on that.

@shivamlko

This comment has been minimized.

Copy link

commented Sep 21, 2018

@Hixie I have FutureBuilder and List to populate in Page 1, when I open Page 2, FutureBuilder runs again and duplicates data, and if I pop Page 2 , then again FutureBuilder runs, hence 3 times duplicate data. i am stuck in this
How to maintain and best way to do not execute any FutureBuilder or StreamBuilder when I call setState()
for now I have to make bool var to stop each widget duplicate data ,I this code of Pagination works but when I call but duplicate when pop from Page 2 or setState() is called

import 'package:flutter/material.dart';
import '../widgets/imageGridItem.dart';
import '../widgets/imageBigGridItem.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import '../utils/constants.dart' as constants;
import '../temp/queries.dart';
import 'package:http/http.dart' as http;
import '../blocs/homebloc.dart';
import 'dart:io';
import 'dart:async';
import 'dart:convert';

class GridListPageState extends State<GridListPage> {
  String endCursorID;
  bool isRefresh = false;
  bool firstTime = true;


  String lastCursor;
  ScrollController controller;
  List listData = new List();

  @override
  void initState() {
    controller = new ScrollController()..addListener(_scrollListener);
    super.initState();
  }

  @override
  void dispose() {
    controller.removeListener(_scrollListener);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {

    print("build");
    if(firstTime) {
      firstTime=false;
      loadMoreData();
    }
    return StreamBuilder(
        stream: bloc.listData,
        builder: (context, snapshot) {
          print('Future $snapshot ');
          if (snapshot.error != null) {
            return Text(snapshot.error.toString());
          }

      
          isRefresh = false;
          if (snapshot.hasData) {
            print(snapshot.data);
            listData.addAll(snapshot.data);

            return dataBody(context);
          }
          if (snapshot.connectionState == ConnectionState.waiting)
            return loadingView();
        }


        );
  }

  Widget dataBody(BuildContext context2) {
    print('Size ${listData.length}');
    return Container(
        color: constants.backgroundColor,
        child: ListView.builder(
            controller: controller,
            itemCount: listData.length == 0 ? 0 : listData.length,
            itemBuilder: (BuildContext context, int index) {
              print('1244');
          
              return addNewItem(listData[index]);
            }));
  }

  Widget addNewItem(var data) {
    print(data['element']['node']['id']);
    return ImageBigGridItem(data);
  }

  void _scrollListener() {
    print('pagination  ');
    if (controller.position.extentAfter < 200) {
    
      if (!isRefresh) {
      
        print('pagin $lastCursor');
        isRefresh = true;
        loadMoreData().then((list) {
       
          setState(() {
            isRefresh = false;
       
          });
        });
      }
    }
  }

  Widget loadingView() {
    return Center(
        child: CircularProgressIndicator(
      backgroundColor: Colors.green,
    ));
  }

 
  Future<List> loadMoreData() async {
    isRefresh = true;


    String body;
    body = json.encode({"query": "{tagview(cursor: $lastCursor)}"});
    print("Outside  $lastCursor $body");

    var url = Uri.parse(
        'https://ueeu1geb42.execute-api.ap-northeast-1.amazonaws.com/staging');
    http.Response response = await http.post(url,
        headers: {
          HttpHeaders.AUTHORIZATION: "Bearer ${constants.apiToken}",
          HttpHeaders.CONTENT_TYPE: "application/json"
        },
        body: body);

    if (response.statusCode == 200) {
      Map data = json.decode(response.body);
      print('JSON $data');
   
      List list = data['data']['tagview']['edges'];
      lastCursor = data['data']['tagview']['pageInfo']['endCursor'];
      print('###$list');
      lastCursor = "\"$lastCursor\"";
      print('End Cursor $lastCursor');
      bloc.addtoList(data['data']['tagview']['edges']);
      bloc.listen();
     
    }
 
  }

 
}

class GridListPage extends StatefulWidget {
  GridListPage() : super();

  @override
  GridListPageState createState() => new GridListPageState();
}
@zoechi

This comment has been minimized.

Copy link
Contributor

commented Sep 24, 2018

@shivamlko you'll need to restructure your code so that the data is not fetched again. For example you can cache it and only fetch from the server if the cached value is null

@and1990

This comment has been minimized.

Copy link

commented Jan 13, 2019

wow. The way widget builds is too complicated for the programmer.

@rrousselGit

This comment has been minimized.

Copy link
Contributor

commented Mar 4, 2019

I'll reference it here because this is a very common question:

This is intended. If this causes any problem for you, then you're likely using widgets incorrectly.

You may want to read https://stackoverflow.com/questions/52249578/how-to-deal-with-unwanted-widget-build, which showcase one of the common pitfall and how to solve it.

@cosinus84

This comment has been minimized.

Copy link

commented Mar 27, 2019

Because of this behaviour when you want to show the status bar when you push A->B: the status bar appears and dissapears again because widget A is rebuild again after widget B build. Widget A hides the status bar, and B has the status bar.

@Afsar-Pasha

This comment has been minimized.

Copy link

commented Apr 13, 2019

Any progress?

@jonmaciel

This comment has been minimized.

Copy link

commented Jun 11, 2019

It's still happening and resending API requests of every stacked page for every pushed page... 😱

@jagrdev

This comment has been minimized.

Copy link

commented Jun 12, 2019

I use stateless widgets for navigation pages where it is posible, because they are not rebuilding or recreating during navigation push or pop and using BlocBuilder for managing their states.

@darren-f5s

This comment has been minimized.

Copy link

commented Jun 17, 2019

So the argument is that 'a widget can rebuild at any time' - I think that's a very lazy blanket answer. Sure, a widget COULD rebuild at any time, but that doesn't mean it SHOULD.

A widget SHOULD need to automatically rebuild ONLY when there's a state change, or a change to one of the children's widget. When Pushing a new page, the previous page is intended not to be used, so what is the possible use case of rebuilding an entire page that isn't currently displaying?

Also, the less build calls the more performance the app inherently has (Especially in the case where Google Maps is one of the widgets). So what is the actual need to rebuild a page that has no visual display?

Really, this is something really stupid to deal with. There aren't even any context flags to notify the developer that the page is now in the background.

Edit A stateless widget should not be the accepted answer.

Edit two For anyone arguing that a rebuild does not affect performance, I beg to differ. In the example of a Google Map widget, the entire widget is built and re-rendered leading to more memory taken. Sure, the GC cleans up, but that clean up is not immediate, such is in the case below (All I did was push a blank route and back a few times)
image

@cic1988

This comment has been minimized.

Copy link

commented Aug 20, 2019

Vote for this problem too. Rebuilding when the stack has been changed certainly not work for the status bar scenario.

@xiarnousx

This comment has been minimized.

Copy link

commented Aug 23, 2019

I had this same behavior when Navigator.of(context).pushNamed(<search-result-route>); to display search results. And when I hit the leading back button of the AppBar the page is popped back to search form however the search query is being executed again.

Solution
I don't know of what I did was a hack or not.

I wrapped the entire widget with WillPopScope as shown below

....
return WillPopScope(
onWillPop: () async {
Navigator.of(context).pushReplacementNamed(<route-to-search-form>);
return false;
},
child: Scaffold(....),
);
....

I don't know if what I did is allowed or not!!!, it is!!! but I mean is that the way to go? 😭

@Hixie

This comment has been minimized.

Copy link
Contributor

commented Aug 23, 2019

@cosinus84 Rather than doing things like showing or hiding status bars in build methods, I would recommend an approach like what we do for styling the color of the status bar (where you post a task to the microtask queue during build that then looks at the status of the tree after the build and decides what to do).

@xiarnousx I don't understand what you are doing that would cause a search query to be executed. Are you triggering the search from a build method or something like that?

@xiarnousx

This comment has been minimized.

Copy link

commented Aug 23, 2019

@Hixie I am tapping over the AppBar back button. Thanks

@xiarnousx

This comment has been minimized.

Copy link

commented Aug 23, 2019

@Hixie Kindly find below two screens

Main Screen That has popup dialog to get in keywords for search

class TutorMainScreen extends StatefulWidget {
  static const String path = '/tutor/main';
  TutorMainScreen({Key key}) : super(key: key);

  _TutorMainScreenState createState() => _TutorMainScreenState();
}

class _TutorMainScreenState extends State<TutorMainScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: tutorHeader(
        context,
        title: 'Gururvise',
        isAppTitle: true,
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.search),
            onPressed: () => _showSearchDialog(),
            iconSize: 40.0,
            tooltip: 'Search for courses by keywords',
          )
        ],
      ),
      body: _buildSearchDirectionWidgets(),
    );
  }

  _showSearchDialog() async {
    List<String> keywords = await showDialog(
        context: context,
        builder: (_) {
          return tutorSearchCoursesDialog();
        });

    Navigator.of(context)
        .pushNamed(TutorCourseSearchResultScreen.path, arguments: keywords);
  }

  Widget _buildSearchDirectionWidgets() {
    return Padding(
      padding: EdgeInsets.symmetric(horizontal: 20, vertical: 50.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          Text(
            'Tap on below search icon to add courses to your profile. Or tap on the header search icon.',
            style: textStyle(
              fontSize: 25,
            ),
          ),
          verticalSpacing(),
          Center(
            child: GestureDetector(
              onTap: () => _showSearchDialog(),
              child: Container(
                alignment: Alignment.center,
                width: 100,
                child: Image.asset('assets/images/search-courses.png'),
              ),
            ),
          ),
          verticalSpacing(),
          Text(
            'Your profile will be searchable by the courses you teach.',
            style: textStyle(
              fontSize: 20.0,
            ),
          ),
        ],
      ),
    );
  }
}

Search Results Screen

class TutorCourseSearchResultScreen extends StatelessWidget {
  static const String path = '/tutor/search/results';

  TutorCourseSearchResultScreen({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final List<String> keywords = ModalRoute.of(context).settings.arguments;
    return WillPopScope(
      onWillPop: () async {
        Navigator.of(context).pushReplacementNamed(TutorMainScreen.path);
        return false;
      },
      child: Scaffold(
        appBar: tutorHeader(
          context,
          title: 'Search Results',
          hasBackButton: true,
        ),
        body: FutureBuilder(
          future: courseModel.search(keywords),
          builder: (_, AsyncSnapshot<List<Course>> snap) {
            if (!snap.hasData) {
              return circularProgress();
            }

            snap.data.forEach((d) {
              print(d.toMap());
            });

            return Text('hello worlds');
          },
        ),
      ),
    );
  }
}

@xiarnousx

This comment has been minimized.

Copy link

commented Aug 23, 2019

My above solution did not prevent calling api again when device is being rotated

However making the stateless widget stateful allowed single call to api note for BLOC I am using scoped_model flutter package

import 'package:flutter/material.dart';
import 'package:guruvise/models/CourseModel.dart';
import 'package:guruvise/widgets/header.dart';
import 'package:guruvise/widgets/progress.dart';
import 'package:scoped_model/scoped_model.dart';

class TutorCourseSearchResultScreen extends StatefulWidget {
  static const String path = '/tutor/search/results';
  TutorCourseSearchResultScreen({Key key}) : super(key: key);

  _TutorCourseSearchResultScreenState createState() =>
      _TutorCourseSearchResultScreenState();
}

class _TutorCourseSearchResultScreenState
    extends State<TutorCourseSearchResultScreen> {
  @override
  void initState() {
    super.initState();
   ///// OVER HERE I AM CALLING FUTURE METHOD THAT CALLS API ////
    Future.delayed(Duration.zero, () async {
      await loadSearchResults();
    });
  }

  Future<void> loadSearchResults() async {
    final List<String> keywords = ModalRoute.of(context).settings.arguments;
//// HERE THE ACTUAL API CALL HAPPENING ///
    await courseModel.search(keywords);
/// THE PRINT STMT ONLY CALLED ONCE ON BACK, ROTATE etc ////
    print('called one time');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: tutorHeader(
        context,
        title: 'Search Results',
        hasBackButton: true,
      ),
      body: ScopedModel<CourseModel>(
        model: courseModel,
        child: ScopedModelDescendant<CourseModel>(
          builder: (_, child, model) {
            if (model.courses.length <= 0) {
              return circularProgress();
            }

            courseModel.courses.forEach((d) {
              print(d.toMap());
            });

            return Text('Hello Worlds');
          },
        ),
      ),
    );
  }
}

@behnam-lum

This comment has been minimized.

Copy link

commented Aug 28, 2019

This might be also related to the problem with MaterialPageRoute wherein certain situations although it's not supposed to, it rebuilds the whole page.
For example, it does the rebuild when a text field gets focus. Take a look at this:
#37878

@RamonJSanchez

This comment has been minimized.

Copy link

commented Sep 4, 2019

Hi,

I'm starting on flutter and I found the same issue, calling push to a route will make your current widget to be rebuild, also in every consecutive push pop for other routes.

In my app I have a MenuButton that send the user to other screen, like this:
IconButton( tooltip: 'Opciones', icon: const Icon(Icons.menu), onPressed: () { Navigator.push(context, MaterialPageRoute( builder: (context) => SettingsScreen(), settings: RouteSettings(name: '/settings') )); }, )

But if I create a new StatelessWidget that just contains the same IconButton and pushes to the same route, my widget is not rebuilt. I think that it has something to do with the context of this "new" widget.
I don't know if this is not a good practice or not, just found out that the behavior is not the same in both cases.

I also have my main widget with WidgetsBindingObserver, and if I use the button inside it (widget is rebuilt) I don't get any calls to didPopRoute, but using the IconButton in it's own StatelessWidget will actually call didPopRoute when a route is popped.

Hope this helps someone.

---I still have an issue with both cases, didPushRoute is never called.

@saviourdog

This comment has been minimized.

Copy link

commented Sep 17, 2019

same shit

@darren-f5s

This comment has been minimized.

Copy link

commented Sep 17, 2019

When a framework developer comes in and basically says "You're doing it wrong" to a heck of a lot of developers experiencing the same issue... That sucks.

I don't understand how such a performance issue (Please see my comments above) can be considered a backlog issue.

@rvowles

This comment has been minimized.

Copy link

commented Sep 17, 2019

@jiyarong

This comment has been minimized.

Copy link

commented Sep 24, 2019

same problem for me, looks like they don't think it's a bug. For now, there will be a lot of works to keep the page state when push to a new page, the prev page will always rebuild, and my temp solution is use mobx/redux/bloc to keep the data will not fetch from remote again and again, but widget's state is still a big problem, I have to find a way to keep a ListView "ScrollState" when I back from next page

@jiyarong

This comment has been minimized.

Copy link

commented Sep 24, 2019

Hi, Is this definitely a bug? I'm confused about it now.

@oscarshaitan

This comment has been minimized.

Copy link

commented Sep 24, 2019

They say that is normal, and your approach with bloc is the ideal, but for me if the framework need a specific architecture to work, is not a good framework (I still love the flutter idea).
also this problem with the problem that the backstack dont have something like garbage colector is a mess, I created a simple app with 5 pages and if I navigate through them, with the time the app get slower and slower

@rrousselGit

This comment has been minimized.

Copy link
Contributor

commented Sep 24, 2019

this problem with the problem that the backstack dont have something like garbage colector is a mess, I created a simple app with 5 pages and if I navigate through them, with the time the app get slower and slower

That's your job to do so.

Flutter expose the necessary tools to free these routes, like:

@jiyarong

This comment has been minimized.

Copy link

commented Sep 25, 2019

how to keep a ListView.builder state, I really really confused about it, the List page build again and again, any body has any solution?

@searchy2

This comment has been minimized.

Copy link

commented Sep 30, 2019

So the entire reason for rebuilding the entire stack is so back buttons can update their UI!?

@Hixie In particular, routes will rebuild because their navigator state has changed so they might need to update how they draw back buttons and the like.

This is a nightmare 😭

@logemann

This comment has been minimized.

Copy link

commented Oct 18, 2019

Suppose i have Dashboard and Logout-Button. Dashboard relies on state objects i will clear on logout action. So right before pushNamed("/login") i clear state and logout via Firebase auth. The Login Screen appears but the stack is filled with errors because Dashboard did rebuild (and tried to access state objects) even though there is zero need because it wont be drawn anyway.

I am not saying that this cant be fixed somehow on my side but its 100% counterintuitive and people spinning their heads for workarounds of similar problems. But perhaps we are all too stupid... even though i think with 20+ years programming experience, i am not a noob either. Furthermore every single example of StreamBuilder i have seen in the web (most likely also from the Flutter team) is based around putting it in the build() method where in fact you most likely get into real trouble doing it this way. So all this is far from perfect.

@rrousselGit

This comment has been minimized.

Copy link
Contributor

commented Oct 18, 2019

@logemann use Navigator.pushReplacementNamed instead. This will unmount the previous route, so it won't rebuild.

Alternatively, you can set maintainState to false on the Route used by DashBoard.
In any case, the default behavior/pushNamed is not what you want.

@darren-f5s

This comment has been minimized.

Copy link

commented Oct 18, 2019

@rrousselGit No, that is not a fix, and will actually negatively affect a project more than the rebuild issue.

(The mentioned 'solution' CAN work, just that it's not what the answer should be. There are VERY MANY cases where you won't push to replace)

@rrousselGit

This comment has been minimized.

Copy link
Contributor

commented Oct 18, 2019

No, that is not a fix, and will actually negatively affect a project more than the rebuild issue.

How so?
That's what he asked for.

@darren-f5s

This comment has been minimized.

Copy link

commented Oct 18, 2019

No, that is not a fix, and will actually negatively affect a project more than the rebuild issue.

How so?
That's what he asked for.

This topic is about the stack rebuilding - current (and future) users are less likely to read every comment to get context, and more likely to skim through everything to find code examples and possible workarounds.

While I did mention your solution CAN work (Which contextually is specific to that question), it's definitely not the solution to the OP's issue. Other users may see that and try to pushReplacementNamed - which will initially work - but lead to issues down the line.

Also, the user that your replied to did not state they they need their login page fully disposed (Maybe they want to go back?), only that he's disposing the Auth object. So in that regard, too, pushReplacementNamed isn't the overall correct answer (As I said, just to emphasize, it IS an answer, but not THE answer).

@rrousselGit

This comment has been minimized.

Copy link
Contributor

commented Oct 18, 2019

Other problems have other solutions that are not about making "build" not being called again.

As described by the tech lead of Flutter, the build method, by design, can be called any number of time.
You should develop your app while keeping that in mind.

Any solution where we're purposefully preventing "build" from being called again is likely to be anti pattern

@darren-f5s

This comment has been minimized.

Copy link

commented Oct 18, 2019

Sorry mate, I think you've lost connection to what this thread is about. There are a LOT of architects on here, all saying the same thing. This IS an issue, no matter how much Flutter thinks it isn't, and it needs to be resolved.

Just to answer the underlying statement there - YES, build ACTIVE pages as much as you want to - you know, because they're ACTIVE. The issue is that Flutter is building pages that aren't even in view. Now there is no argument that can substantiate why that should happen.

@rrousselGit

This comment has been minimized.

Copy link
Contributor

commented Oct 18, 2019

That's what maintainState is here for.

If the Route is not visible and has maintainState: false, it'll be unmounted. But, as opposed to pushReplacement, we can still use the back button to show the Route again.

@logemann

This comment has been minimized.

Copy link

commented Oct 18, 2019

To be honest i didnt want to bring up personal programming issues on this thread but merely wanted to state that the flutter way of handling the build cycle will lead to massive "onboarding" issues for new developers with flutter in general. Nevertheless i will try to look into your suggestion regarding the Route, but i doubt its the nature of the problem. The problem was my Drawer, i think it rebuilt (after i cleared state) because of the animation attached to it after clicking on logout item !?

The overall problem is, you need to know a lot of inner workings of Flutter to code without errors. But i admit that clearing state, logging out and having problems with redrawn Widgets is not everyday work. And i am still amazed how many people use StreamBuilder (possibly with Firestore) in the build() method without any caution. Google will be happy $$$ but IMO the flutter team must, if not find another way, at least document such behaviours way better.

@oscarshaitan

This comment has been minimized.

Copy link

commented Oct 19, 2019

and to be worst all the examples that you can find from flutter team use the StreamBuilder inside build(), Im not architect but im not a noob, and that is a big fail, also build a view that is not in the screen is a waste of resources.
In general Im happy with Flutter but this issue is kind annoying for me. hopefully Flutter team will listen to the developers

@escamoteur

This comment has been minimized.

Copy link
Contributor

commented Oct 19, 2019

One aspect that wasn't named is that any page that you push can ce transparent or have transparent regions. So you have to update the pages below too.

@edwjusti

This comment has been minimized.

Copy link

commented Oct 22, 2019

As far as I understood the rebuild is necessary to pass the new build context down to the widget tree if it has changed. But this is quite expensive given that users will inevitably be doing computed tasks inside build such as mapping a list to a widget list and doing string manipulations. I wonder why flutter couldn't hold and update the context in a class property instead of passing it in the build method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.