Flutter 不在 ListView 中显示有状态 children Widget
Flutter does not display stateful children Widget in ListView
如标题所示,我对 ListView 有疑问,希望您能帮助我。
我正在使用基本的 ListView 构建“Card Widgets”(具有自己的状态)。 ListView 使用 ID 列表,用于构建那些“Card Widgets”
问题:
每当我通过删除一个 Id 从列表中删除一张卡片时,ListView 总是会删除最上面的 Child 小部件。我的后端删除了正确的东西,因为在我重新启动应用程序以便重新填充页面后,删除的卡片实际上被删除了,被 ListView 删除的卡片再次可见。似乎 ListView 没有重绘它是 children。知道发生了什么事吗?
我创建了基本的 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]。这里发生了什么?我错过了什么吗?
您的 CRD 小部件是一个 StatefulWidget,重建时将重用状态,因为小部件的类型是相同的,您没有给它一个密钥。
要解决您的问题,有以下几种可能性:
- 为列表中的所有项目添加一个键
- 在您的小部件状态下实施
didUpdateWidget
方法
- 使用无状态小部件并在构建方法中进行字符串连接
如标题所示,我对 ListView 有疑问,希望您能帮助我。
我正在使用基本的 ListView 构建“Card Widgets”(具有自己的状态)。 ListView 使用 ID 列表,用于构建那些“Card Widgets”
问题: 每当我通过删除一个 Id 从列表中删除一张卡片时,ListView 总是会删除最上面的 Child 小部件。我的后端删除了正确的东西,因为在我重新启动应用程序以便重新填充页面后,删除的卡片实际上被删除了,被 ListView 删除的卡片再次可见。似乎 ListView 没有重绘它是 children。知道发生了什么事吗?
我创建了基本的 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]。这里发生了什么?我错过了什么吗?
您的 CRD 小部件是一个 StatefulWidget,重建时将重用状态,因为小部件的类型是相同的,您没有给它一个密钥。
要解决您的问题,有以下几种可能性:
- 为列表中的所有项目添加一个键
- 在您的小部件状态下实施
didUpdateWidget
方法 - 使用无状态小部件并在构建方法中进行字符串连接