Flutter ListView performance issues with PageStorageKey

1,154

If all of your ListView children have the same height, ListView has a property called itemExtent, which you can specify your child's height in double. This will considerably improve your scroll performance.

If your ListView children have difference height, then there is not much you can do, but if you are testing this out in debug mode, try it out in release mode instead. Scroll behavior is a log laggy in debug mode than in release mode.

Share:
1,154
kungfuslippers
Author by

kungfuslippers

Updated on December 20, 2022

Comments

  • kungfuslippers
    kungfuslippers over 1 year

    I have a TabBar which contains two ListViews - each with 250 items. I am using a PageStorageKey for each ListView to preserve the scroll position when switching between views.

    If I switch between tabs initially when the scroll position hasn't changed much - say at the start of the list, switching between tabs is crisp and quick.

    However, if I scroll to the end of each list and switch between the two tabs then there is a noticeable lag before the list is actually displayed.

    Is there anything I can do to improve the performance here?

    See : https://gist.github.com/kungfuslippers/fcae96675fb76c10f7bb5051b66ed87e

    or code below:

    import 'package:flutter/foundation.dart';
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp(
          itemsA: List<String>.generate(250, (i) => "Item $i"),
          itemsB: List<String>.generate(250, (i) => "Item $i")));
    }
    
    class MyApp extends StatefulWidget {
      final List<String> itemsA;
      final List<String> itemsB;
    
      MyApp({Key key, @required this.itemsA, this.itemsB}) : super(key: key);
    
      @override
      MyAppState createState() => MyAppState();
    }
    
    class MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
      TabController _tabController;
    
      final Key listKeyA = PageStorageKey('listA');
      final Key listKeyB = PageStorageKey('listB');
    
    
      @override
      void initState() {
        super.initState();
        _tabController = TabController(vsync: this, length: 2);
      }
    
      @override
      Widget build(BuildContext context) {
        final title = 'Long List';
    
        return MaterialApp(
            title: title,
            home: Scaffold(
              appBar: AppBar(
                title: Text(title),
              ),
              body: TabBarView(controller: _tabController, children: [
                ListWidget(key: listKeyA, items: widget.itemsA),
                ListWidget(key: listKeyB, items: widget.itemsB),
              ]),
              bottomNavigationBar: Container(
                color: Colors.blue,
                child: TabBar(
                  controller: _tabController,
                  indicatorColor: Colors.white,
                  tabs: <Widget>[Tab(text: "ListA"), Tab(text: "ListB")],
                ),
              ),
            ));
      }
    }
    
    class ListWidget extends StatefulWidget {
      final List<String> items;
    
      const ListWidget({
        Key key,
        @required this.items,
      }) : super(key: key);
    
      @override
      ListWidgetState createState() => ListWidgetState();
    }
    
    class ListWidgetState extends State<ListWidget> {
      @override
      Widget build(BuildContext context) {
        return ListView.builder(
          itemCount: widget.items.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text('${widget.items[index]}'),
            );
          },
        );
      }
    }
    
  • kungfuslippers
    kungfuslippers almost 4 years
    This issue isn't to do with scroll performance. Scrolling is fine and smooth. There is a lag / delay between selecting the tab containing the long list of items and the list of items actually appearing.
  • dshukertjr
    dshukertjr almost 4 years
    @kungfuslippers When PageStorageKey is used, it has to layout all of the children up until it reaches the scroll position. That is why you are having some issue rendering it when you have scroll a big amount. My answer will solve that problem. Have you tried it?
  • kungfuslippers
    kungfuslippers almost 4 years
    Yes, you're right it improves performance considerably. Many thanks.