Empty state page and Navigator issues?

2019-07-15 03:02发布

I want to implement empty state page in Flutter app, when news feed is empty.

When there is no activity in feed, I want to show ‘no activity’. When database has data, I want to load this from StreamBuilder to ListView.builder

I try implement with:

child: StreamBuilder(
    stream: collection.snapshots(),
    builder: (context, snapshot) {

    if(snapshot.hasData) {
       return ListView.builder(
            itemBuilder: (context, index) =>
                build(context, snapshot.data.documents[index]),
            itemCount: snapshot.data.documents.length,
         );
      } else {
          return _emptyStateWidget();
      }

I must return something in else statement because sometimes snapshot will not have data so will throw error that Widget return null.

But this is causing issues with widget tree. Because if I try to use Navigator.push in build Widget later:

Widget build(BuildContext context, DocumentSnapshot document) {
…
FlatButton(
  onPressed: () async {

await function(document);

if(validated == true) {
await Navigator.push(context, new MaterialPageRoute(
    builder: (BuildContext context) =>
    new Screen(documentInfo: documentInfo)));
}

Error is thrown:

Looking up a deactivated widget's ancestor is unsafe. At this point the state of the widget's element tree is no longer stable. To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling inheritFromWidgetOfExactType() in the widget's didChangeDependencies() method.

Is there way to avoid this so that no error is thrown?

For some reason if I call Navigator.push before await function(document) there is no error thrown. But I cannot allow this because it must perform data validation in function before and only navigate if success.

Thanks!

UPDATE:

After more test I think problem is cause by StreamBuilder. It rebuild whenever it get new event. So this cause issue when call Navigator.push and it get new event so try to rebuild.

How to solve? Is possible to stop StreamBuilder from rebuild descendant?

1条回答
仙女界的扛把子
2楼-- · 2019-07-15 03:52

That happens because you are trying to navigate to somewhere else while your widget tree is still being built.

You should move the Navigation.push to a stream listener, for example, in your initState.

void initState() {
super.initState();
collection.snapshots.listen((data){

if(validated == true) {
   await Navigator.push(context, new MaterialPageRoute(
      builder: (BuildContext context) =>
      new Screen(documentInfo: documentInfo)));
  }
});

}
查看更多
登录 后发表回答