Flutter 在 ListView 中不显示有状态的子 Widget

Posted

技术标签:

【中文标题】Flutter 在 ListView 中不显示有状态的子 Widget【英文标题】:Flutter does not display stateful children Widget in ListView 【发布时间】:2021-02-07 10:49:07 【问题描述】:

如标题所示,我对 ListView 有疑问,希望您能帮帮我。

我正在使用基本的 ListView 来构建“卡片小部件”(具有自己的状态)。 ListView 使用一个 Id 列表,用于构建那些“卡片小部件”

问题: 每当我通过删除 Id 从列表中删除卡片时,ListView 总是会删除最顶部的子小部件。我的后端删除了正确的内容,因为在我重新启动应用程序以便重新填充页面后,已删除的卡片实际上已被删除,而被 ListView 删除的卡片再次可见。似乎 ListView 没有重绘它的孩子。有什么想法吗?

我创建了基本的 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);
  

因此,单击一次添加按钮后,列表内容为 [A,Q,B,C,D],但应用程序显示 [A,B,C,D,D]。这里发生了什么?我错过了什么吗?

【问题讨论】:

【参考方案1】:

您的 CRD 小部件是 StatefulWidget,并且在重建时将重用该状态,因为小部件的类型与您未给它键的类型相同。

要解决您的问题,有几种可能性:

    为列表中的所有项目添加一个键 在您的小部件状态中实现didUpdateWidget 方法 使用无状态小部件并在构建方法中进行字符串连接

【讨论】:

好的,所以基本上我根据我的小部件实例在“didUpdateWidget”中填充我的小部件状态?我需要这样做,因为底层状态被重用而不是再次创建。那正确吗?实施“didUpdateWidget”得到了我预期的结果!谢谢! 好吧,部分是的,didUpdateWidgetbis 仅在重建时才调用,因此您还需要在 initState 中执行此操作 好的,非常感谢!添加密钥似乎是我想做的最简单的事情。祝你有美好的一天:)

以上是关于Flutter 在 ListView 中不显示有状态的子 Widget的主要内容,如果未能解决你的问题,请参考以下文章

Flutter ListView scrollPhysics 在 SingleChildScrollView 中不起作用

滚动条不显示flutter web

Flutter - 在一个屏幕上显示两个 ListView

Flutter—ListView嵌套ListView不显示的问题

Flutter—ListView嵌套ListView不显示的问题

Flutter—ListView嵌套ListView不显示的问题