【问题标题】:How to reposition widget without rebuilding its children in Flutter?如何重新定位小部件而不在 Flutter 中重建其子级?
【发布时间】:2021-01-14 10:12:08
【问题描述】:

在我的 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

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

所以我的问题是:有没有办法防止每次重新定位列表时重新构建每个项目,有没有办法缓存列表渲染,以提高性能同时重新定位?

谢谢。

【问题讨论】:

    标签: flutter dart flutter-animation


    【解决方案1】:

    当您调用setState(() =&gt; _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
            ...
                
    

    【讨论】:

    • 谢谢。也就是说,经过一些测试,它并没有提高性能,如果我旋转屏幕,我可能会遇到一些问题,例如,如果我在 initList() 函数中使用 MediaQuery.of(context) ......你知道吗?
    • 您遇到了什么样的性能问题?
    • 当我使用GestureDetector 小部件移动带有平移事件的列表时,帧速率约为 24 fps,这非常糟糕(并不可怕,但仍远低于预期的 60 fps.. .)
    • 假设您在调试模式下尝试过。释放模式呢?
    • 不,在发布模式下(实际上是配置文件模式)......但我继续调查,问题可能出在其他地方。
    猜你喜欢
    • 2020-09-29
    • 2020-03-14
    • 2021-10-29
    • 2021-03-03
    • 2019-08-24
    • 1970-01-01
    • 2020-03-18
    • 1970-01-01
    • 2019-12-09
    相关资源
    最近更新 更多