AutomaticKeepAliveClientMixin Causing Multiple Pull-to-Refresh Calls in TabBarView's each tab"

106 views Asked by At

I have a Flutter app with a nested tabbed view where each tab contains a pull-to-refresh functionality using RefreshIndicator. The issue I'm facing is that when I pull-to-refresh on one tab, the onRefresh function is getting triggered for all tabs, even though I only want it to trigger for the currently active tab.

I believe this problem is occurring because I'm using AutomaticKeepAliveClientMixin with wantKeepAlive set to true in each tab to preserve their state when switching between tabs. This mixin keeps the state of the widgets alive even when they are not in the current view.

Here is my code for refrence

class MiniAppScaffold extends StatefulWidget {
  const MiniAppScaffold({super.key});

  @override
  State<MiniAppScaffold> createState() => _MiniAppScaffoldState();
}

class _MiniAppScaffoldState extends State<MiniAppScaffold> {
  List<int> data = [0, 1, 2];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: DefaultTabController(
          length: 3,
          child: NestedScrollView(
            headerSliverBuilder: (context, innerBoxIsScrolled) {
              return [
                SliverToBoxAdapter(
                  child: Container(
                    color: Colors.blue,
                    child: const Center(
                      child: Column(
                        children: [
                          SizedBox(
                            height: 200,
                            child: Text(
                              'Widget 1',
                              style: TextStyle(color: Colors.white, fontSize: 20),
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
                SliverPersistentHeader(
                  delegate: _SliverAppBarDelegate(
                    const TabBar(
                      tabs: [
                        Tab(text: 'Explore'),
                        Tab(text: 'Transactions'),
                        Tab(text: 'Holdings'),
                      ],
                    ),
                  ),
                  pinned: true,
                ),
              ];
            },
            body: TabBarView(children: data.map((e) => EachTabView(index: e)).toList() ?? []),
          ),
        ),
      ),
    );
  }
}
class EachTabView extends StatefulWidget {
  final int? index;
  const EachTabView({super.key, required this.index});

  @override
  State<EachTabView> createState() => _EachTabViewState();
}

class _EachTabViewState extends State<EachTabView> with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return RefreshIndicator(
      onRefresh: () {
        return Future.delayed(const Duration(milliseconds: 10), () {
          //code
        });
      },
      child: Scaffold(
        body: ListView.builder(
          itemCount: 500,
          itemBuilder: (context, index) => Container(
            height: 50,
            color: Colors.grey[300],
            alignment: Alignment.center,
            child: Column(
              children: [
                Text('Explore Item $index'),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
  • I kept the wantKeepAlive property to be false and in this case, it works as expected, but It's important for me to keep it true

  • I am considering of doing custom implementation of storing current index and adding a check in onRefresh if there is no other solution

0

There are 0 answers