所以我这几天一直在尝试解决这个问题,我似乎在这里遇到了一个真正的死胡同。
问题(我在下面的代码中简化了)是当我尝试从 a 中删除一个项目时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在屏幕上向上移动了,但是状态中的颜色信息并没有被删除。
任何尝试的想法将不胜感激。