所以我已经尝试解决这个问题几天了,我似乎在这里遇到了真正的死胡同。
问题(我在下面的代码中已简化)是当我尝试从 List<"SomeDataObject">
中删除项目时,它实际上从列表中删除了正确的对象。这很明显,因为我任意分配给对象的 ID 确实会发生变化,正如我在删除某些内容时所期望的那样。然而,奇怪的是,即使 ID 在列表中移动并删除了正确的 ID,所有小部件的状态似乎总是删除最后一个项目,即使删除的对象位于中间甚至开头的名单。
一个例子是,如果列表看起来像这样:
Data(id: 630) // This one starts blue
Data(id: 243) // Let's say the user made this one red
Data(id: 944) // Also blue
假设我试图从这个列表中删除中间项目。好吧,列表现在看起来像这样:Data(id: 630)
Data(id: 944)
起初这似乎很棒,因为它看起来正是我想要的,但出于某种原因,颜色没有改变它们的顺序,仍然是先红色,然后是蓝色。颜色状态数据似乎独立于实际对象运行,我找不到明确的解决方案。我有一个示例程序的代码来重现这个问题,我还在程序下面放了一些图片,以便更清楚地说明问题是什么。
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: HomeScreen(),
);
}
}
// Home screen class to display app
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
List<DataWidget> widgetsList = List<DataWidget>();
// Adds a new data object to the widgets list
void addData() {
setState(() {
widgetsList.add(DataWidget(removeData));
});
}
// Removes a given widget from the widgets list
void removeData(DataWidget toRemove) {
setState(() {
widgetsList = List.from(widgetsList)..remove(toRemove);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
/* I used a SingleChildScrollView instead of ListView because ListView
resets an objects state when it gets out of view so I wrapped the whole
list in a column and then passed that to the SingleChildScrollView to
force it to stay in memory. It is worth noting that this problem still
exists even when using a regular ListView. */
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
// Added a SizedBox just to make column take up whole screen width
children: [...widgetsList, SizedBox(width: double.infinity)],
),
),
// FloatingActionButton just to run addData function for example
floatingActionButton: FloatingActionButton(onPressed: addData),
);
}
}
// Simple class that is a red square that when clicked turns blue when pressed
class DataWidget extends StatefulWidget {
DataWidget(this.onDoubleTap);
final Function(DataWidget) onDoubleTap;
// Just a random number to keep track of which widget this is
final String id = Random.secure().nextInt(1000).toString();
@override
String toStringShort() {
return id;
}
@override
_DataWidgetState createState() => _DataWidgetState();
}
class _DataWidgetState extends State<DataWidget> {
/* Here the example state information is just a color, but in the full version
of this problem this actually has multiple fields */
Color color = Colors.red;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
// onDoubleTap this passes itself to the delete method of the parent
onDoubleTap: () => widget.onDoubleTap(widget),
// Changes color on tap to whatever color it isn't
onTap: () {
setState(() {
color = color == Colors.red ? Colors.blue : Colors.red;
});
},
child: Container(
child: Center(child: Text(widget.id)),
width: 200,
height: 200,
color: color,
),
),
);
}
}
在用户更改任何颜色之前(对象 ID 在容器上显示为文本):用户通过点击将中间容器更改为蓝色:
用户尝试通过双击删除中间(蓝色)容器:
从上图可以看出,ID 被删除,下方的 ID 在屏幕上向上移动,但状态中的颜色信息并没有被删除。
任何尝试的想法将不胜感激。
最佳答案
您需要对您的 DataWidget
进行一些更改类使其工作:
// Simple class that is a red square that when clicked turns blue when pressed
class DataWidget extends StatefulWidget {
Color color = Colors.red; // moved from _DataWidgetState class
DataWidget(this.onDoubleTap);
final Function(DataWidget) onDoubleTap;
// Just a random number to keep track of which widget this is
final String id = Random.secure().nextInt(1000).toString();
@override
String toStringShort() {
return id;
}
@override
_DataWidgetState createState() => _DataWidgetState();
}
class _DataWidgetState extends State<DataWidget> {
/* Here the example state information is just a color, but in the full version
of this problem this actually has multiple fields */
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
// onDoubleTap this passes itself to the delete method of the parent
onDoubleTap: () => widget.onDoubleTap(widget),
// Changes color on tap to whatever color it isn't
onTap: () {
setState(() {
widget.color =
widget.color == Colors.red ? Colors.blue : Colors.red;
});
},
child: Container(
child: Center(child: Text(widget.id)),
width: 200,
height: 200,
color: widget.color,
),
),
);
}
}
关于flutter - List.remove() 删除了正确的对象,但列表中对象的状态发生了变化,就好像最后一个条目正在被删除一样,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63627430/