Flutter中如何为ListView每个卡片递增索引实现Firestore文档删除
Flutter Firestore 列表卡片删除功能修复

原方案的核心问题
你靠自增索引定位待删除文档的思路完全不可行,代码里也存在语法错误:
- 你在State根层级定义了
final index = 0,又试图在Card组件内部写final index = index + 1实现自增:首先Card构造函数不支持随意写变量声明语句,其次final修饰的变量初始化后不可修改,就算语法能过,所有卡片拿到的索引值也不会按你预期逐次递增 - Firestore集合的文档返回顺序不是永久固定的,新增、删除、修改排序规则后,靠位置索引匹配到的文档和你点击的卡片根本无法一一对应,大概率会删错数据
- 你在
map遍历列表的时候已经拿到了当前卡片对应的DocumentSnapshot document对象,完全不需要绕路通过索引反查文档,直接用这个对象就能拿到准确的文档引用。
修复后的可运行代码
删掉所有无效的索引定义,直接在删除按钮的回调里使用当前遍历到的document对象执行删除即可:
class _ArticleDataState extends State<ArticleData> { final Stream<QuerySnapshot> _usersStream = FirebaseFirestore.instance.collection('Article').snapshots(); @override Widget build(BuildContext context) { return StreamBuilder<QuerySnapshot>( stream: _usersStream, builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) { if (snapshot.hasError) { return const Text('Something went wrong'); } if (snapshot.connectionState == ConnectionState.waiting) { return const Text("Loading"); } return ListView( children: snapshot.data!.docs.map((DocumentSnapshot document) { Map<String, dynamic> data = document.data()! as Map<String, dynamic>; return Card( elevation: 3.0, margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0), child: Container( decoration: BoxDecoration( color: Theme.of(context).colorScheme.surface), child: ListTile( contentPadding: const EdgeInsets.symmetric( horizontal: 20.0, vertical: 10.0), title: Text( data['name'], style: TextStyle( color: Theme.of(context).colorScheme.primary, fontWeight: FontWeight.bold), ), subtitle: Wrap( children: <Widget>[ Text(data["text"], overflow: TextOverflow.ellipsis, style: TextStyle( color: Theme.of(context).colorScheme.secondary)) ], ), trailing: IconButton( icon: const Icon(FontAwesomeIcons.solidTrashCan, color: Colors.blue, size: 25.0), onPressed: () { // 直接调用当前文档的引用执行删除,无需索引匹配 document.reference.delete().then( (doc) => showDialog( context: context, builder: (BuildContext context) => _buildPopupDialog(context), ) ); }, ), ), ), ); }).toList(), ); }, ); } }
开发建议
- 后续做列表项的增删改操作时,只要是在遍历回调里渲染单项,直接用回调返回的当前元素对象操作对应数据,不要手动维护位置索引,列表顺序一旦变动索引就会完全失效
- 如果后续列表数据量变大换用
ListView.builder做懒加载,也不要靠传入的index参数去取文档ID,提前把遍历到的文档引用存在当前项的作用域里,从根源上避免删错数据 - 删除操作建议加二次确认弹窗,用户点垃圾桶后先弹提示确认要删除,再执行删除逻辑,避免误触。
内容的提问来源于stack exchange,提问作者Erwan Cloux
相关产品推荐
相关产品推荐

