Flutter中基于TextField输入的Firestore Where查询无结果问题
问题分析与解决方案
核心问题
你的代码里,StreamBuilder的stream直接用t6.text初始化,但当t6输入内容变化时,这个stream不会自动更新。输入框内容改变本身不会触发setState,导致Firestore一直用初始的t6.text值执行查询,自然得不到匹配输入的结果。
解决步骤
- 动态更新查询流:在State类中定义变量存储查询流,通过
t6的监听器,在输入变化时调用setState更新流,让StreamBuilder感知条件变化并重新查询。 - 处理输入空格:对
t6.text做trim()处理,避免前后空格导致查询条件与Firestore中存储的内容不匹配。
修改后的代码示例
class YourDoctorSelector extends StatefulWidget { @override _YourDoctorSelectorState createState() => _YourDoctorSelectorState(); } class _YourDoctorSelectorState extends State<YourDoctorSelector> { final TextEditingController t6 = TextEditingController(); final TextEditingController t7 = TextEditingController(); Stream<QuerySnapshot>? _doctorStream; @override void initState() { super.initState(); // 初始化初始查询流 _refreshDoctorStream(); // 监听输入变化,实时更新查询条件 t6.addListener(() { setState(() { _refreshDoctorStream(); }); }); } void _refreshDoctorStream() { final department = t6.text.trim(); // 输入为空时返回空流,避免无效查询 if (department.isEmpty) { _doctorStream = Stream.value(QuerySnapshot.empty); return; } _doctorStream = FirebaseFirestore.instance.collection('Doctors') .where("Department", isEqualTo: department) .snapshots(); } @override void dispose() { t6.dispose(); t7.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return StreamBuilder<QuerySnapshot>( stream: _doctorStream, builder: (context, snapshot) { if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); } if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } final documents = snapshot.data?.docs ?? []; return TypeAheadFormField( validator: (value) { if (value == null || value.isEmpty) { return 'Please Select Doctor'; } return null; }, suggestionsBoxDecoration: const SuggestionsBoxDecoration( borderRadius: BorderRadius.all(Radius.circular(5)), color: Colors.blue, ), textFieldConfiguration: TextFieldConfiguration( controller: t7, keyboardType: TextInputType.text, decoration: InputDecoration( border: OutlineInputBorder(), focusedBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), suffixIcon: IconButton( icon: const Icon(Icons.clear), onPressed: () => t7.clear(), ), label: const Text( "Search Doctor", style: TextStyle(color: Colors.black), ), ), ), suggestionsCallback: (query) async { if (query.isEmpty) return []; final filteredDocs = documents.where((doc) => doc['Doc_Name'].toString().toLowerCase().contains(query.toLowerCase())); return filteredDocs.map((doc) => doc['Doc_Name']).toList(); }, itemBuilder: (context, suggestion) { return ListTile(title: Text(suggestion.toString())); }, onSuggestionSelected: (suggestion) { setState(() => t7.text = suggestion.toString()); }, ); }, ); } }
额外提示
- 确保
t6和t7控制器在dispose方法中释放,避免内存泄漏。 - 如果Firestore中
Department字段大小写不统一,可以将查询条件和存储值统一转成小写(比如department.toLowerCase()),避免因大小写差异导致查询失败。
内容的提问来源于stack exchange,提问作者Zubair Malik
相关产品推荐
相关产品推荐

