Flutter:如何将类内变量传入Future函数更新Firestore数据?
解决方法
核心思路是让updateData函数接收文档引用作为参数,点击保存按钮时直接把当前条目的Firestore文档引用传递进去即可,具体实现如下:
步骤1:修改updateData函数,添加文档引用参数
把原本无参的updateData改成带DocumentReference参数的函数,直接用传入的引用执行更新操作:
Future updateData(DocumentReference docRef) async { await docRef.update({ 'name': controllerName.text, }).then((value) => print('updated.')); }
步骤2:在条目构建方法中传递文档引用
在_buildListItem里给文档引用定义一个明确的变量(比如docRef),然后在调用updateData时把这个变量传进去:
DataRow _buildListItem(BuildContext context, DocumentSnapshot data) { // 定义当前条目的Firestore文档引用 final docRef = FirebaseFirestore.instance .collection('testinfo') .doc(data.id); return DataRow(cells: [ DataCell(Text(data['name']!)), DataCell(Row(children: [ PopupMenuButton<Menu>( padding: const EdgeInsets.only(right: 2, left: 1, top: 2), onSelected: (value) async { if (value == Menu.itemOne) { controllerName.text = data.get('name'); showDialog( context: context, builder: (context) => Dialog( child: Container( color: primaryColor, child: Padding( padding: const EdgeInsets.all(8.0), child: ListView( shrinkWrap: true, children: <Widget>[ TextField( onChanged: (value) { candidateName = value; }, controller: controllerName, decoration: const InputDecoration( hintText: 'name', ), ), const SizedBox(height: 16), ElevatedButton( // 传入当前条目的文档引用 onPressed: () => updateData(docRef), child: const Text('Save'), ), ], ), ), ), ), ); } }, itemBuilder: (BuildContext context) => const <PopupMenuEntry<Menu>>[ PopupMenuItem<Menu>( value: Menu.itemTwo, child: Text('edit'), ), ], ), ])), ]); }
完整修正后的代码
import 'package:flutter/material.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; // 补充代码中用到的Menu枚举 enum Menu { itemOne, itemTwo } class Test extends StatefulWidget { const Test({Key? key}) : super(key: key); @override State<Test> createState() => _TestState(); } class _TestState extends State<Test> { final Stream<QuerySnapshot> _usersStream = FirebaseFirestore.instance.collection('testinfo').snapshots(); // 补充代码中用到的控制器和变量 final TextEditingController controllerName = TextEditingController(); String candidateName = ''; // 补充代码中用到的常量定义 final double defaultPadding = 16.0; final Color primaryColor = Colors.white; @override Widget build(BuildContext context) { return Container( padding: EdgeInsets.all(defaultPadding), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ StreamBuilder<QuerySnapshot>( stream: _usersStream, builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) { if (snapshot.hasError) { return const Center(child: CircularProgressIndicator()); } if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: Text("Loading")); } return SizedBox( width: double.infinity, child: DataTable( columnSpacing: defaultPadding, columns: const [ DataColumn( label: Text('Text'), ), ], rows: _buildList(context, snapshot.data!.docs), ), ); }, ), ], ), ); } List<DataRow> _buildList(BuildContext context, List<DocumentSnapshot> snapshot) { return snapshot.map((data) => _buildListItem(context, data)).toList(); } DataRow _buildListItem(BuildContext context, DocumentSnapshot data) { final docRef = FirebaseFirestore.instance .collection('testinfo') .doc(data.id); return DataRow(cells: [ DataCell(Text(data['name']!)), DataCell(Row(children: [ PopupMenuButton<Menu>( padding: const EdgeInsets.only(right: 2, left: 1, top: 2), onSelected: (value) async { if (value == Menu.itemOne) { controllerName.text = data.get('name'); showDialog( context: context, builder: (context) => Dialog( child: Container( color: primaryColor, child: Padding( padding: const EdgeInsets.all(8.0), child: ListView( shrinkWrap: true, children: <Widget>[ TextField( onChanged: (value) { candidateName = value; }, controller: controllerName, decoration: const InputDecoration( hintText: 'name', ), ), const SizedBox(height: 16), ElevatedButton( onPressed: () => updateData(docRef), child: const Text('Save'), ), ], ), ), ), ), ); } }, itemBuilder: (BuildContext context) => const <PopupMenuEntry<Menu>>[ PopupMenuItem<Menu>( value: Menu.itemTwo, child: Text('edit'), ), ], ), ])), ]); } Future updateData(DocumentReference docRef) async { await docRef.update({ 'name': controllerName.text, }).then((value) => print('updated.')); } }
内容的提问来源于stack exchange,提问作者matto
相关产品推荐
相关产品推荐

