Android List.remove()删除正确的对象,但对象';列表中的状态发生变化,就好像最后一个条目被删除一样
所以我已经尝试解决这个问题好几天了,我似乎已经走到了死胡同 问题是(我在下面的代码中简化了这一点)当我试图从Android List.remove()删除正确的对象,但对象';列表中的状态发生变化,就好像最后一个条目被删除一样,android,flutter,dart,Android,Flutter,Dart,所以我已经尝试解决这个问题好几天了,我似乎已经走到了死胡同 问题是(我在下面的代码中简化了这一点)当我试图从列表中删除一个项目时,它实际上从列表中删除了正确的对象。这是很明显的,因为我任意分配给对象的ID确实会发生移动,就像我移除某些东西时所期望的那样。然而,奇怪的是,即使ID在列表中移动并且正确的ID被删除,所有小部件的状态似乎都好像最后一项总是被删除一样,即使删除的对象位于列表的中间甚至开始 例如,如果列表看起来是这样的: Data(id: 630) // This one starts b
列表
中删除一个项目时,它实际上从列表中删除了正确的对象。这是很明显的,因为我任意分配给对象的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,
),
),
);
}
}
import'dart:math';
进口“包装:颤振/材料.省道”;
void main(){
runApp(MyApp());
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“颤振演示”,
主页:主屏幕(),
);
}
}
//显示应用程序的主屏幕类
类主屏幕扩展StatefulWidget{
@凌驾
_HomeScreenState createState()=>\u HomeScreenState();
}
类_homescrenstate扩展状态{
List-widgetsList=List();
//将新数据对象添加到窗口小部件列表
void addData(){
设置状态(){
add(DataWidget(removeData));
});
}
//从窗口小部件列表中删除给定的窗口小部件
void removeData(DataWidget toRemove){
设置状态(){
widgetsList=List.from(widgetsList)…删除(toRemove);
});
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
/*我使用了SingleChildScrollView而不是ListView,因为ListView
在对象离开视图时重置对象状态,因此我将整个对象包装起来
列表,然后将其传递给SingleChildScrollView以
强制将其保留在内存中。值得注意的是,此问题仍然存在
即使在使用常规ListView时也存在*/
正文:SingleChildScrollView(
子:列(
mainAxisAlignment:mainAxisAlignment.center,
//添加了一个大小框,使列占据整个屏幕宽度
子项:[…widgetsList,SizedBox(宽度:double.infinity)],
),
),
//例如,FloatingActionButton只是为了运行addData函数
floatingActionButton:floatingActionButton(按下:添加数据),
);
}
}
//一个简单的类,它是一个红色的正方形,当单击它时,按下它时会变成蓝色
类DataWidget扩展了StatefulWidget{
DataWidget(this.onDoubleTap);
最终功能(DataWidget)onDoubleTap;
//只是一个随机数来跟踪这是哪个小部件
最终字符串id=Random.secure().nextInt(1000.toString();
@凌驾
字符串到字符串短(){
返回id;
}
@凌驾
_DataWidgetState createState();
}
类_DataWidgetState扩展状态{
/*这里的示例状态信息只是一种颜色,但是完整版本
这个问题实际上有多个字段*/
颜色=颜色。红色;
@凌驾
小部件构建(构建上下文){
返回填充(
填充:常数边集全部(8.0),
儿童:手势检测器(
//onDoubleTap将其自身传递给父级的delete方法
onDoubleTap:()=>widget.onDoubleTap(widget),
//将点击时的颜色更改为其他颜色
onTap:(){
设置状态(){
color=color==Colors.red?Colors.blue:Colors.red;
});
},
子:容器(
子:中心(子:文本(widget.id)),
宽度:200,
身高:200,
颜色:颜色,
),
),
);
}
}
用户更改任何颜色之前(对象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,
),
),
);
}
}
//一个简单的类,它是一个红色的正方形,单击时会变成蓝色
类DataWidget扩展了StatefulWidget{
Color Color=Colors.red;//从_DataWidgetState类移动
DataWidget(this.onDoubleTap);
最终功能(DataWidget)onDoubleTap;
//只是一个随机数来跟踪这是哪个小部件
最终字符串id=Random.secure().nextInt(1000.toString();
@凌驾
字符串到字符串短(){
返回id;
}
@凌驾
_DataWidgetState createState();
}
类_DataWidgetState扩展状态{
/*这里的示例状态信息只是一种颜色,但是完整版本
这个问题实际上有多个字段*/
@凌驾
小部件构建(构建上下文){
返回填充(
填充:常数边集全部(8.0),
儿童:手势检测器(
//onDoubleTap将其自身传递给父级的delete方法
onDoubleTap:()=>widget.onDoubleTap(widget),
//变色