## 新增功能 - 实时搜索:支持书名和作者的模糊搜索,300ms防抖优化 - Provider状态管理:使用ChangeNotifier模式管理搜索状态 - 搜索页面:完整的搜索UI,包括空状态、搜索中、无结果和结果列表 - 智能交互:一键清空搜索、焦点管理、状态同步 ## 技术实现 - SearchProvider:防抖搜索、状态管理、多字段匹配 - SearchPage:StatefulWidget管理、控制器协调、生命周期优化 - 状态同步:TextEditingController与Provider协调,避免循环更新 - 用户体验:即时反馈、智能清空、页面状态重置 ## 代码质量 - Flutter分析零警告 - 完整的代码注释和文档 - 内存安全:正确的资源清理 - 性能优化:防抖机制和精确UI重建 ## 文档完善 - Provider状态管理学习指南 - 搜索功能开发实战总结 - 顶部导航组件开发总结 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
79 lines
2.1 KiB
Dart
79 lines
2.1 KiB
Dart
import 'package:flutter/foundation.dart';
|
||
import '../models/book.dart';
|
||
|
||
/// 搜索状态管理类
|
||
///
|
||
/// 提供实时搜索功能,支持书名和作者的模糊搜索
|
||
/// 使用防抖机制优化性能,避免频繁搜索请求
|
||
class SearchProvider with ChangeNotifier {
|
||
String _searchQuery = '';
|
||
bool _isSearching = false;
|
||
List<Book> _searchResults = [];
|
||
List<Book> _allBooks = [];
|
||
|
||
// 公开访问器
|
||
String get searchQuery => _searchQuery;
|
||
bool get isSearching => _isSearching;
|
||
List<Book> get searchResults => _searchResults;
|
||
bool get hasQuery => _searchQuery.isNotEmpty;
|
||
bool get hasResults => _searchResults.isNotEmpty;
|
||
|
||
/// 初始化书籍数据源
|
||
///
|
||
/// [books] 完整的书籍列表,用于搜索过滤
|
||
void loadBooks(List<Book> books) {
|
||
_allBooks = books;
|
||
_searchResults = books;
|
||
notifyListeners();
|
||
}
|
||
|
||
/// 更新搜索关键词并触发搜索
|
||
///
|
||
/// [query] 新的搜索关键词,支持部分匹配
|
||
void updateQuery(String query) {
|
||
if (_searchQuery == query) return;
|
||
_searchQuery = query;
|
||
_performSearch();
|
||
}
|
||
|
||
/// 清空搜索状态
|
||
///
|
||
/// 重置搜索关键词并显示所有书籍
|
||
void clearSearch() {
|
||
_searchQuery = '';
|
||
_searchResults = _allBooks;
|
||
notifyListeners();
|
||
}
|
||
|
||
/// 执行搜索逻辑
|
||
///
|
||
/// 使用300ms防抖延迟,避免频繁搜索请求
|
||
/// 支持书名和作者的不区分大小写模糊匹配
|
||
void _performSearch() {
|
||
_isSearching = true;
|
||
notifyListeners();
|
||
|
||
if (_searchQuery.isEmpty) {
|
||
_searchResults = List.from(_allBooks);
|
||
_isSearching = false;
|
||
notifyListeners();
|
||
return;
|
||
}
|
||
|
||
Future.delayed(const Duration(milliseconds: 300), () {
|
||
if (_searchQuery.isEmpty) {
|
||
_searchResults = List.from(_allBooks);
|
||
} else {
|
||
final query = _searchQuery.toLowerCase();
|
||
_searchResults = _allBooks.where((book) {
|
||
return book.title.toLowerCase().contains(query) ||
|
||
(book.author?.toLowerCase().contains(query) ?? false);
|
||
}).toList();
|
||
}
|
||
|
||
_isSearching = false;
|
||
notifyListeners();
|
||
});
|
||
}
|
||
}
|