Flutter中SearchDelegate如何实现输入内容变化时实时查询数据库
解决方案
你可以通过以下两种方式实现搜索框输入变化的监听,两种方式都可以达到和TextField.onChanged一致的触发效果:
方式1:重写updateQuery方法(更灵活,推荐)
SearchDelegate内部自带updateQuery方法,每次用户增删搜索框字符时都会自动调用该方法,直接重写即可拿到最新的输入内容,按需执行数据库查询。建议搭配防抖逻辑避免频繁查询数据库影响性能。
修改后的完整代码如下:
import 'dart:async'; import 'package:flutter/material.dart'; class DataSearch extends SearchDelegate<String>{ // 存储查询到的建议列表 List<String> _suggestionList = []; // 防抖定时器 Timer? _debounceTimer; @override void updateQuery(String newQuery) { super.updateQuery(newQuery); // 输入变化时先取消上一次未执行的查询任务 if (_debounceTimer?.isActive ?? false) _debounceTimer!.cancel(); // 延迟300ms执行查询,用户停止输入300ms后才触发查询,可自行调整时间 _debounceTimer = Timer(const Duration(milliseconds: 300), () async { // 替换为你自己的数据库查询逻辑 _suggestionList = await _queryFromDatabase(newQuery); // 通知UI刷新 notifyListeners(); }); } @override List<Widget>? buildActions(BuildContext context) { return [ IconButton( onPressed: () {query = '';}, icon: const Icon(Icons.clear)) ]; } @override Widget? buildLeading(BuildContext context) { return IconButton( onPressed: (){close(context, '');}, icon: AnimatedIcon( progress: transitionAnimation, icon: AnimatedIcons.menu_arrow )); } @override Widget buildResults(BuildContext context) { //TODO 基于选中的内容展示结果 return Scaffold(); } @override Widget buildSuggestions(BuildContext context) { final showList = query.isEmpty ? [] : _suggestionList; return ListView.builder( itemBuilder: (context, index) => ListTile( onTap: () { // 点击建议项可直接填入搜索框并展示结果 query = showList[index]; showResults(context); }, title: RichText( text: TextSpan( text: showList[index].substring(0, query.length), style: const TextStyle(color: Colors.black, fontWeight: FontWeight.bold), children: [ TextSpan( text: showList[index].substring(query.length), style: const TextStyle(color: Colors.grey)) ]), ), ), itemCount: showList.length, ); } @override void close(BuildContext context, String result) { // 销毁时取消定时器避免内存泄漏 _debounceTimer?.cancel(); super.close(context, result); } // 示例数据库查询方法,替换为你自己的实现 Future<List<String>> _queryFromDatabase(String keyword) async { // 这里执行你的真实数据库查询逻辑 await Future.delayed(const Duration(milliseconds: 100)); return ['苹果', '香蕉', '橙子', '葡萄', '芒果'] .where((element) => element.contains(keyword)) .toList(); } }
方式2:直接在buildSuggestions中处理
如果不需要额外的逻辑控制,也可以直接在buildSuggestions方法中执行查询,该方法会在每次query更新时自动触发,同样需要加防抖逻辑避免频繁查询。
内容的提问来源于stack exchange,提问作者Lorenzo Cutrupi
相关产品推荐
相关产品推荐

