Flutter中FutureBuilder的snapshot.data赋值列表后修改列表为何同步改原数据
核心原因
这是Dart的对象引用传递特性导致的:
- Dart中
int、bool、String这类基础类型是值传递,赋值时会复制一份新的值;但List、Map、自定义类等复合类型都是引用传递,赋值时只会传递内存地址,不会复制对象本身 - 执行
ticketList = snapshot.data时,你并没有创建新的列表,只是让ticketList指向了snapshot.data对应的同一块内存空间,两个变量本质上操作的是同一个列表对象 - 所以不管通过哪个变量修改列表内容,另一个变量读取到的都是修改后的结果
解决方案
如果需要两个列表完全独立互不影响,需要先创建列表的副本再做修改,常用的浅拷贝写法有两种:
- 使用
toList()方法创建副本
List<TicketModel> ticketList = snapshot.data.toList();
- 使用展开运算符创建副本
List<TicketModel> ticketList = [...snapshot.data];
你提供的简化示例修改为拷贝赋值后,就不会出现原列表被修改的问题:
void main() { List<String> listofAllTickets = ["ticket eins","ticket zwei", "ticket drei"]; // 先拷贝原列表再赋值 List<String> listOfAllTicketsSecond = listofAllTickets.toList(); listOfAllTicketsSecond.removeWhere((element) => element == "ticket eins"); print(listofAllTickets); // 输出:[ticket eins, ticket zwei, ticket drei] print(listOfAllTicketsSecond); // 输出:[ticket zwei, ticket drei] }
补充说明
上述写法属于浅拷贝,如果列表中存储的是自定义类对象(比如你的TicketModel),浅拷贝只能保证列表本身独立,如果你修改列表中单个对象的属性,原列表内的对应对象还是会被修改。如果需要完全的深拷贝,可以给自定义类实现克隆方法:
class TicketModel { int price; String title; TicketModel({required this.price, required this.title}); // 自定义克隆方法 TicketModel clone() => TicketModel(price: price, title: title); } // 深拷贝列表写法 List<TicketModel> ticketList = snapshot.data.map((item) => item.clone()).toList();
内容的提问来源于stack exchange,提问作者Carla
相关产品推荐
相关产品推荐

