调整大小后,如何防止Flutter列表视图重建子级?

时间:2019-11-24 15:14:10

标签: flutter

我喜欢Flutter,但是我遇到了性能问题。考虑以下简单示例:

import 'package:flutter/material.dart';

void main() => runApp(MyHomePage());

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() {
    return _MyHomePageState();
  }
}

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  static const elements = [
    'Element 1',
    'Element 2',
    'Element 3',
    'Element 4',
    'Element 5',
    'Element 6',
    'Element 7',
    'Element 8',
    'Element 9',
    'Element 10'
  ];
  String selectedElement = elements[0];
  double listViewHeight = 200;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Simple test')),
        body: Column(
          children: <Widget>[
            Slider(
              value: listViewHeight,
              min: 100,
              max: 300,
              onChanged: (double newValue) => setState(() => listViewHeight = newValue),
            ),
            Text('Selected: ' + selectedElement),
            Container(
              height: listViewHeight,
              child: ListView(
                children: elements
                    .map((id) => Element(
                          id: id,
                          color: id == selectedElement ? Colors.green : Colors.lightGreen,
                          onTap: (newElement) => setState(() => selectedElement = newElement),
                        ))
                    .toList(),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class Element extends StatelessWidget {
  final String id;
  final Color color;
  final Function onTap;

  Element({this.id, this.color, this.onTap});

  @override
  Widget build(context) {
    print('Building ' + id);
    return GestureDetector(
      onTap: () => onTap(id),
      child: Container(
        height: 100,
        margin: EdgeInsets.all(2),
        alignment: Alignment.center,
        color: color,
        child: Text(id),
      ),
    );
  }
}

这很好用,当我使用滑块调整列表视图的大小时,一切都变得流畅。我在现实世界中的例子要复杂得多。列表视图中的每个子视图都是另一个(水平)列表视图,其中的子视图包含小的SVG图像。在列表视图内部滚动时,一切都很流畅,但是在调整外部列表视图本身的大小时,它变得非常跳跃。

我意识到在调整列表视图大小时,所有(可见)列表视图子级都会一直重建。我的第一个想法是:这很有道理。当事情发生变化时,Flutter会重建一切。然后我意识到,滚动列表视图本身时,不会重建这些子项(除非将另一个子项滚动到视图中)。

这就像列表视图在说:“我不需要仅因为滚动位置改变而重建子代。我只需将它们移动即可。”很有道理。

现在我的问题当然是,我该怎么做?就像:“移动滑块时,我不需要重建列表视图。我只是调整当前列表视图的大小而无需重建它。

0 个答案:

没有答案