简体   繁体   English

Flutter 不在ListView中显示stateful children Widget

[英]Flutter does not display stateful children Widget in ListView

As in the titel, I have a problem with ListView and I hope you can help me out.如标题所示,我对 ListView 有疑问,希望您能帮助我。

I am using a basic ListView to build "Card Widgets" (with their own state).我正在使用基本的 ListView 来构建“Card Widgets”(具有自己的状态)。 The ListView uses a List of Ids, which are used to build those "Card Widgets" ListView 使用一个 ID 列表,用于构建那些“Card Widgets”

The problem: Any time I remove a card from the list by deleting an Id the ListView always removes the top most Child Widget.问题:每当我通过删除一个 Id 从列表中删除一张卡片时,ListView 总是会删除最上面的子窗口小部件。 My backend deletes the right things, becouse after I restart the app so that the page gets populated anew, the deleted card is actually deleted and the one the removed by the ListView is visible again.我的后端删除了正确的东西,因为在我重新启动应用程序以便重新填充页面后,删除的卡片实际上被删除了,被 ListView 删除的卡片再次可见。 It seems like ListView does not redraw it's children.似乎 ListView 没有重绘它的孩子。 Any Idea what is going on?知道发生了什么事吗?

I created basic DartPad code to illustrate the problem我创建了基本的 DartPad 代码来说明问题

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  List<String> dd = new List<String>();
  
  @override
  void initState() {
    super.initState();
    dd.add('A');
    dd.add('B');
    dd.add('C');
    dd.add('D');
  }

  

  void _incrementCounter() {
    setState(() {
      _counter++;
      dd.insert(1, 'Q');
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title + _counter.toString()),
      ),
      body: ListView.builder(
        addAutomaticKeepAlives: false,
        itemBuilder: (context, index) {
          print('calling: $index :' + _counter.toString() + ' -> ' + dd[index] );
          return new CRD(title: dd[index]);
        },
        itemCount: dd.length
      ),
      /*
      ListView(
        children: dd.map((str) {
          return CRD(title: str);
        }).toList()
      ),
      */
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

class CRD extends StatefulWidget {
  
  CRD({Key key, this.title}) : super(key: key);

  final String title;
  @override
  _CRD createState() => _CRD();
}

class _CRD extends State<CRD> {

  String _val;
  
  @override
  void initState() {
    super.initState();
    _val = widget.title + ' ' + widget.title;
  }

  @override
  Widget build(BuildContext context) {
    return Text(_val);
  }
}

So after clicking once on the Add button the list content is [A,Q,B,C,D] but the app displays [A,B,C,D,D].因此,在单击“添加”按钮后,列表内容为 [A,Q,B,C,D],但应用程序显示 [A,B,C,D,D]。 Whats going on here?这里发生了什么? Am i missing something?我错过了什么吗?

Your CRD widget is a StatefulWidget and the state will be reused when rebuilding since the type of the widget is the same an you did not give it a key.您的 CRD 小部件是一个 StatefulWidget 并且 state 将在重建时被重用,因为小部件的类型是相同的并且您没有给它一个密钥。

To solve your issue there are a few possibilities:要解决您的问题,有几种可能性:

  1. Add a key to all the items in the list为列表中的所有项目添加一个键
  2. Implement the didUpdateWidget method in the state of your widget在您的小部件的 state 中实现didUpdateWidget方法
  3. Use a statelesswidget and do the string concatination in the build method使用无状态小部件并在构建方法中进行字符串连接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM