Flutter - 刷新后的奇怪ListView行为

时间:2018-02-07 11:33:28

标签: dart flutter

他们可以帮我解决并理解为什么ListView在刷新后的奇怪行为?

在下面的示例中,我创建了一个包含24个元素的列表,然后转到列表中的最后一项,然后点击将更新列表的icone刷新。只有在更新后,ListView才会显示所有元素。

并确保每个元素在randomString

中始终具有不同的键

enter image description here

import 'package:flutter/material.dart';
import 'dart:math';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new CategoryPage(),
    );
  }
}

class CategoryPage extends StatefulWidget {
  @override
  CategoryPageState createState() => new CategoryPageState();
}

class CategoryPageState extends State<CategoryPage> {
  Color blueAppBar = new Color(0xFF26C6DA);
  List<Widget> listCategories = [];
  List listaDB = [];
  var listaCategory;

  String randomString(int length) {
    var rand = new Random();
    var codeUnits = new List.generate(
        length, 
        (index){
          return rand.nextInt(33)+89;
        }
    );   
    return new String.fromCharCodes(codeUnits);
  }

  @override
  void initState() {
    this.listaDB = 
      [
        [{'category': 'foo01'}],
        [{'category': 'foo02'}],
        [{'category': 'foo03'}],
        [{'category': 'foo04'}],
        [{'category': 'foo05'}],
        [{'category': 'foo06'}],
        [{'category': 'foo07'}],
        [{'category': 'foo08'}],
        [{'category': 'foo09'}],
        [{'category': 'foo10'}],
        [{'category': 'foo11'}],
        [{'category': 'foo12'}],
        [{'category': 'foo13'}],
        [{'category': 'foo14'}],
        [{'category': 'foo15'}],
        [{'category': 'foo16'}],
        [{'category': 'foo17'}],
        [{'category': 'foo18'}],
        [{'category': 'foo19'}],
        [{'category': 'foo20'}],
        [{'category': 'foo21'}],
        [{'category': 'foo22'}],
        [{'category': 'foo23'}],
        [{'category': 'foo24'}]
      ];
  }

  @override
  Widget build(BuildContext context) {

    List<Widget> buildListCategories(List list) {
      this.listCategories = [];

      for(var i in list) {
        var category = i[0]['category'];

        this.listCategories.add(
          new ItemCategory(
            key: new Key(randomString(20)),
            category: category,
          )
        );  
      }
      return this.listCategories;
    }

    this.listaCategory = buildListCategories(this.listaDB);

    return new Scaffold( 
      appBar: new AppBar(
        title: new Text('Categories'),
        backgroundColor: blueAppBar,
        actions: <Widget>[
          new IconButton(
            icon: new Icon(Icons.refresh),
            onPressed: () {
              setState(() {
                this.listaCategory = buildListCategories(this.listaDB);
              });
            },
          )
        ],
      ),
      body: new ListView(
        padding: new EdgeInsets.only(top: 8.0, right: 0.0, left: 0.0),
        children: this.listaCategory
      ),
    );
  }
}

class ItemCategory extends StatelessWidget {
  final String category;

  ItemCategory({
    Key key,
    this.category}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return new Container(
      decoration: new BoxDecoration(
        border: new Border(
          top: new BorderSide(style: BorderStyle.solid, color: Colors.black26),
        ),
        color: new Color(0xFFFAFAFA),
      ),
      margin: new EdgeInsets.only(top: 0.0, bottom: 0.0),
      child: new Row(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          new Expanded(
            child: new Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                new Container(
                  margin: new EdgeInsets.only(left: 16.0),
                  padding: new EdgeInsets.only(right: 40.0, top: 4.5, bottom: 4.5),
                  child: new Row(
                    children: <Widget>[
                      new Container(
                        margin: new EdgeInsets.only(right: 16.0),
                        child: new Icon(
                          Icons.brightness_1,
                          color: Colors.black,
                          size: 35.0,
                        ),
                      ),
                      new Text(this.category),
                    ],
                  )
                )
              ],
            ),
          )
        ],
      ),
    );
  }
}

2 个答案:

答案 0 :(得分:1)

如果按下按钮(在setState和build方法中),仍然会调用buildListCategories两次,但这不是问题。我也不会嵌套这些方法。显然钥匙出了问题。如果你没有设置密钥,一切都很好。我不确定为什么会破坏列表视图,但我也不认为它会增加任何内容。

我用固定代码作出了要点:https://gist.github.com/renefloor/0fed1bbd43567b45ed2605f57ecce29f

答案 1 :(得分:0)

由于问题出在keyListView也需要key,因为在更新到其他列表时,如果每个列表都没有自己的key列表以错误的方式安装。

ListView代码应如下所示:

body: new ListView(
  key: new Key(randomString(20)), //new
  padding: new EdgeInsets.only(top: 8.0, right: 0.0, left: 0.0),
  children: this.listaCategory
),

通过进行此更改,列表已正确安装。