如何重新定位小部件而不重建其子在颤振?



在我的Flutter项目中,我想在屏幕上重新定位列表,使用Positioned小部件,因此用户可以手动或通过使用动画移动列表。

我所做的工作很好,但是我发现,每次移动列表时,列表中的每一项都要重新构建,这会导致一些性能问题。

下面是一个基本的例子:

class TestPositionedPage extends StatefulWidget {
  @override
  _TestPositionedPageState createState() => _TestPositionedPageState();
}
class _TestPositionedPageState extends State<TestPositionedPage> {
  double _yPage = 0;
  Widget _getItem(int position) {
    print("get item at $position");
    return ListTile(title: Text("Item at position $position"));
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Stack(
          children: [
            Align(
              alignment: Alignment.topRight,
              child: FlatButton(
                onPressed: () {
                  setState(() => _yPage = Random().nextDouble() * 500);
                },
                child: Text("MOVE"),
                color: Colors.redAccent,
              ),
            ),
            Positioned(
              left: 0,
              top: _yPage,
              child: Container(
                width: 700,
                height: 700,
                child: ListView.builder(
                  itemCount: 100,
                  itemBuilder: (BuildContext context, int position) => _getItem(position),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

在这个例子中,有一个按钮,每次我点击这个按钮,它都会随机重新定位列表。但是每次列表被重新定位时,我在控制台中看到的是:

I/flutter (17851): get item at 0
I/flutter (17851): get item at 1
I/flutter (17851): get item at 2
I/flutter (17851): get item at 3
I/flutter (17851): get item at 4
I/flutter (17851): get item at 5
I/flutter (17851): get item at 6
I/flutter (17851): get item at 7
I/flutter (17851): get item at 8
I/flutter (17851): get item at 9
I/flutter (17851): get item at 10
I/flutter (17851): get item at 11
I/flutter (17851): get item at 12
I/flutter (17851): get item at 13
I/flutter (17851): get item at 14
I/flutter (17851): get item at 15
I/flutter (17851): get item at 16

这意味着每次列表被重新定位时,它也会被重建,即使列表中没有任何变化。

所以我的问题是:是否有一种方法可以防止每次重新定位列表时每个项目都被重建,是否有一种方法可以缓存列表呈现,以便在重新定位时提高性能?

谢谢。

当您调用setState(() => _yPage = Random().nextDouble() * 500);时,整个树再次被重建,从而导致列表也被重建。相反,只构建一次列表,并在需要时重用。

Widget _myList;
  
  Widget initList(){
   return ListView.builder(
      itemCount: 100,
      itemBuilder: (BuildContext context, int position) => _getItem(position),
    );
  }
  @override
  void initState() {
    _myList = initList();
    super.initState();
  }

然后以这种方式使用列表

Positioned(
    left: 0,
    top: _yPage,
    child: Container(
        width: 700,
        height: 700,
        child: _myList
        ...
            

最新更新