zerochill
zerochill

Reputation: 746

How can i stop my this future builder to stop reloading as i switch my botom navigation bar?

This is that builder which i just want to load once. I'm using a bottom navigation bar and this widget is in one of the tab; and as i switch between tabs this widget rebuilds. This widget doesn't rebuilds when i press on a grid tile and goes to the detail screen and come back to. It only rebuilds when i am switching between tabs.

class PostGridScreen extends StatefulWidget {
  @override
  _PostGridScreenState createState() => _PostGridScreenState();
}

class _PostGridScreenState extends State<PostGridScreen> {
  @override
  void initState() {
    Future.delayed(Duration.zero).then((value) =>
        Provider.of<BaseProvider>(context, listen: false).getPosts());

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Claw Shop"),
        centerTitle: true,
      ),
      body: FutureBuilder(
          future: Provider.of<BaseProvider>(context).getPosts(),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return Center(
                child: Text("Loading..."),
              );
            } else {
              return GridView.builder(
                  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 2,
                      childAspectRatio: 3 / 2,
                      crossAxisSpacing: 10,
                      mainAxisSpacing: 10),
                  itemCount: snapshot.data.length,
                  itemBuilder: (context, index) {


                    return ItemGridTile();
                  });
            }
          }),
    );
  }
}

Upvotes: 0

Views: 469

Answers (1)

Dan James
Dan James

Reputation: 579

You could try using the AutomaticKeepAliveClientMixin. This will prevent the widget from being destroyed. You override the wantKeepAlive to choose when you want the widget to be destroyed. Below will always keep the widget alive. I have also moved the future to a class field so that it is not called in the build method (which can happen multiple times).

  @override
  bool get wantKeepAlive => true;

Note: you must call the super.build(context) with this mixin.

Edit: try making sure you are only building when connection state is done. You could also add other if else statements for other connection states.

class PostGridScreen extends StatefulWidget {
  @override
  _PostGridScreenState createState() => _PostGridScreenState();
}

class _PostGridScreenState extends State<PostGridScreen> with AutomaticKeepAliveClientMixin {
  Future _getPosts;
  @override
  void initState() {
 
  _getPosts = Provider.of<BaseProvider>(context, listen: false).getPosts();

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(
      appBar: AppBar(
        title: Text("Claw Shop"),
        centerTitle: true,
      ),
      body: FutureBuilder(
          future: _getPosts,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.done) {
              return GridView.builder(
                  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 2,
                      childAspectRatio: 3 / 2,
                      crossAxisSpacing: 10,
                      mainAxisSpacing: 10),
                  itemCount: snapshot.data.length,
                  itemBuilder: (context, index) {


                    return ItemGridTile();
                  });
            } else {
                return Center(
                    child: Text("Loading..."),
              );
              
            }
          }),
    );
  }

  @override
  bool get wantKeepAlive => true;
}

Upvotes: 2

Related Questions