Flutter ListWidget重复添加删除项问题求助
问题解决:Flutter列表重复添加/删除异常
问题描述
- 首次添加列表条目正常,第二次开始添加会出现多个重复项,添加2个条目后列表显示4个重复项
- 删除条目时,除第一个外其余条目会被删除两次
错误原因
核心问题出在ListView.builder的实现逻辑上:
- 你设置了
itemCount: names.length,意味着会生成与列表长度一致的条目数量 - 但在
itemBuilder中,每个条目都渲染了整个names列表转换成的Widget数组,相当于每个条目都重复显示一遍完整列表,导致内容叠加。例如names有2个元素时,ListView生成2个条目,每个条目里又显示2个Text,最终呈现2×2=4个重复项;删除时,每次removeLast减少一个元素,ListView的条目数和每个条目内的列表长度同时减少,视觉上就像删除了两次。
修正后的代码
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); static const String title = 'Flutter Sample'; @override Widget build(BuildContext context) { return MaterialApp( title: title, home: Scaffold( appBar: AppBar(title: const Text(title)), body: const MyStatefulWidget())); } } class MyStatefulWidget extends StatefulWidget { const MyStatefulWidget({super.key}); @override State<MyStatefulWidget> createState() => MyStatefulWidgetState(); } class MyStatefulWidgetState extends State<MyStatefulWidget> { bool light = true; final List<String> names = <String>[]; TextEditingController nc = TextEditingController(); void addItemToList() { setState(() { names.add(nc.text); }); } void deleteItemFromList() { setState(() { if(names.isNotEmpty) { // 防止空列表删除报错 names.removeLast(); } }); } void clearInput() { setState(() { nc.text = ""; }); } bool x = false; void setInput() { setState(() { x = !x; // 原代码x != x是无效赋值,修正为取反 }); } @override Widget build(BuildContext context) { Widget test1 = const Text("Hello Flutter"); Widget test2 = Padding( padding: const EdgeInsets.all(20), child: TextField( enabled: true, controller: nc, decoration: const InputDecoration( border: OutlineInputBorder(), labelText: 'Name'))); Widget test3 = SwitchListTile( value: x, onChanged: (bool value) { setState(() { x = value; }); }); Widget buttons = SizedBox( width: 1000, height: 30, child: Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ Expanded( child: TextButton( onPressed: clearInput, child: const Text('ClearInput'))), Expanded( child: TextButton(onPressed: addItemToList, child: const Text('Add'))), Expanded( child: TextButton( onPressed: deleteItemFromList, child: const Text('Remove'))) ])); Widget mylist = ListView.builder( scrollDirection: Axis.vertical, shrinkWrap: true, padding: const EdgeInsets.all(8), itemCount: names.length, itemBuilder: (BuildContext context, int index) { // 直接返回当前索引对应的单个Text,不再渲染整个列表 return Container( padding: const EdgeInsets.symmetric(vertical: 8), child: Text(names[index])); }); return Scaffold( // 移除嵌套的MaterialApp,避免上下文冲突 resizeToAvoidBottomInset: false, body: SingleChildScrollView( scrollDirection: Axis.vertical, child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisSize: MainAxisSize.min, children: <Widget>[ Container( padding: const EdgeInsets.all(5), child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ test1, test2, test3, buttons, mylist ])) ]))); } }
关键修改点
- 修复ListView核心逻辑:在
itemBuilder中直接返回当前索引对应的单个Text(names[index]),每个条目仅显示对应位置的内容,不再重复渲染整个列表 - 修正无效代码:将
setInput方法中的x != x改为x = !x,实现开关状态取反 - 优化结构:移除
build方法内重复的MaterialApp,避免上下文冲突 - 增加异常防护:在删除方法中添加空列表判断,防止数组越界报错
- 性能优化:给静态Widget和常量参数添加
const修饰符,减少不必要的重建
内容的提问来源于stack exchange,提问作者DktPhl2018
相关产品推荐
相关产品推荐

