# Provider状态管理学习指南 ## 📚 什么是Provider? Provider是Flutter官方推荐的状态管理解决方案,它提供了一种简单、高效的方式来在应用中共享和传递数据。 ### 核心概念 - **Provider**: 数据提供者,封装状态数据 - **Consumer**: 数据消费者,监听数据变化并重建UI - **ChangeNotifier**: 状态变化通知器,当数据改变时通知监听者 ## 🎯 为什么需要状态管理? ### 问题场景 ```dart // 问题:多个页面需要共享搜索状态 class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { String searchText = ''; // 局部状态,无法跨页面共享 return AppHeader(onSearchPressed: () { // 无法将搜索文本传递给其他页面 }); } } class SearchPage extends StatelessWidget { @override Widget build(BuildContext context) { // 无法获取首页的搜索状态 return Text('搜索结果'); } } ``` ### Provider解决方案 ```dart // 解决方案:使用Provider全局共享状态 class SearchProvider extends ChangeNotifier { String _searchText = ''; List _searchResults = []; String get searchText => _searchText; List get searchResults => _searchResults; void updateSearchText(String text) { _searchText = text; notifyListeners(); // 通知所有监听者重建 } void performSearch() { // 执行搜索逻辑 _searchResults = _searchBooks(_searchText); notifyListeners(); } } ``` ## 🔧 Provider使用步骤 ### 步骤1: 添加依赖 ```yaml dependencies: flutter: sdk: flutter provider: ^6.0.5 # 添加provider依赖 ``` ### 步骤2: 创建状态管理类 ```dart import 'package:flutter/foundation.dart'; class SearchProvider extends ChangeNotifier { // 私有状态变量 String _searchQuery = ''; bool _isSearching = false; List _results = []; // 公共getter方法 String get searchQuery => _searchQuery; bool get isSearching => _isSearching; List get results => _results; // 状态更新方法 void updateQuery(String query) { _searchQuery = query; notifyListeners(); // 通知UI更新 } void searchBooks(String query) { _isSearching = true; notifyListeners(); // 模拟异步搜索 Future.delayed(const Duration(milliseconds: 500), () { _results = _performSearch(query); _isSearching = false; notifyListeners(); }); } void clearSearch() { _searchQuery = ''; _results.clear(); notifyListeners(); } // 私有搜索方法 List _performSearch(String query) { if (query.isEmpty) return []; // 实际搜索逻辑 return []; } } ``` ### 步骤3: 在应用根部提供Provider ```dart void main() { runApp( ChangeNotifierProvider( create: (context) => SearchProvider(), child: const ReadfulApp(), ), ); } ``` ### 步骤4: 在UI中消费Provider数据 ```dart // 方法1: 使用Consumer Widget Consumer( builder: (context, searchProvider, child) { return Text('搜索词: ${searchProvider.searchQuery}'); }, ) // 方法2: 使用Provider.of TextButton( onPressed: () { final searchProvider = Provider.of(context, listen: false); searchProvider.updateQuery('Flutter'); }, child: Text('搜索'), ) // 方法3: 使用Selector(性能优化) Selector>( selector: (context, provider) => provider.results, builder: (context, results, child) { return ListView.builder( itemCount: results.length, itemBuilder: (context, index) { return BookTile(book: results[index]); }, ); }, ) ``` ## 🎨 实际应用:搜索功能实现 ### 搜索状态管理 ```dart class SearchProvider extends ChangeNotifier { String _query = ''; List _filteredBooks = []; List _allBooks = []; // 数据源 // Getters String get query => _query; List get filteredBooks => _filteredBooks; bool get hasResults => _filteredBooks.isNotEmpty; bool get isEmpty => _query.isEmpty; // 初始化数据 void loadBooks(List books) { _allBooks = books; _filteredBooks = books; notifyListeners(); } // 更新搜索查询 void updateQuery(String newQuery) { _query = newQuery.toLowerCase(); _filterBooks(); notifyListeners(); } // 过滤书籍 void _filterBooks() { if (_query.isEmpty) { _filteredBooks = List.from(_allBooks); } else { _filteredBooks = _allBooks.where((book) { return book.title.toLowerCase().contains(_query) || book.author.toLowerCase().contains(_query) || book.description.toLowerCase().contains(_query); }).toList(); } } // 清空搜索 void clearSearch() { _query = ''; _filteredBooks = List.from(_allBooks); notifyListeners(); } } ``` ### 搜索页面UI ```dart class SearchPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Column( children: [ // 搜索输入框 _buildSearchBar(context), // 搜索结果 Expanded( child: Consumer( builder: (context, provider, child) { if (provider.isEmpty) { return _buildEmptyState(); } else if (provider.hasResults) { return _buildResultsList(provider.filteredBooks); } else { return _buildNoResults(); } }, ), ), ], ), ); } Widget _buildSearchBar(BuildContext context) { return Container( padding: const EdgeInsets.all(16), child: TextField( onChanged: (value) { Provider.of(context, listen: false) .updateQuery(value); }, decoration: InputDecoration( hintText: '搜索书名、作者或内容...', prefixIcon: const Icon(Icons.search), suffixIcon: Consumer( builder: (context, provider, child) { return provider.query.isNotEmpty ? IconButton( icon: const Icon(Icons.clear), onPressed: () { Provider.of(context, listen: false) .clearSearch(); }, ) : const SizedBox.shrink(); }, ), ), ), ); } } ``` ## 💡 Provider最佳实践 ### 1. 性能优化 ```dart // ❌ 错误:每次重建都执行复杂计算 Consumer( builder: (context, provider, child) { return HeavyComputationWidget(data: provider.complexData); }, ) // ✅ 正确:使用Selector优化 Selector( selector: (context, provider) => provider.computedData, builder: (context, data, child) { return HeavyComputationWidget(data: data); }, ) ``` ### 2. 合理拆分Provider ```dart // ❌ 错误:一个Provider管理太多状态 class AppProvider extends ChangeNotifier { // 搜索状态 String searchQuery = ''; List searchResults = []; // 用户状态 User? currentUser; bool isLoggedIn = false; // 主题状态 bool isDarkMode = false; Color accentColor = Colors.blue; } // ✅ 正确:按功能拆分Provider class SearchProvider extends ChangeNotifier { /* 搜索相关 */ } class UserProvider extends ChangeNotifier { /* 用户相关 */ } class ThemeProvider extends ChangeNotifier { /* 主题相关 */ } ``` ### 3. 错误处理 ```dart class SearchProvider extends ChangeNotifier { bool _isLoading = false; String? _errorMessage; bool get isLoading => _isLoading; String? get errorMessage => _errorMessage; Future searchAsync(String query) async { _isLoading = true; _errorMessage = null; notifyListeners(); try { final results = await _apiService.search(query); _updateResults(results); } catch (e) { _errorMessage = e.toString(); } finally { _isLoading = false; notifyListeners(); } } } ``` ## 🎯 学习总结 ### 关键概念 - **ChangeNotifier**: 状态管理基类,提供notifyListeners()方法 - **Consumer**: 监听Provider变化并自动重建UI - **Selector**: 性能优化的Consumer,只监听特定数据变化 - **Provider.of**: 手动获取Provider实例的方式 ### 使用场景 - ✅ **全局状态**: 用户信息、主题设置 - ✅ **页面间共享**: 搜索状态、购物车数据 - ✅ **复杂数据**: 表单状态、异步加载状态 ### 注意事项 - 避免在build方法中创建Provider实例 - 合理使用listen参数控制是否需要重建 - 及时dispose防止内存泄漏 - 使用Selector优化UI重建性能 --- *下一步:我们将使用Provider来实现Readful的搜索功能!*