资讯动态

Flutter Provider 状态管理完全指南

发布时间:2026/8/14 19:47:09 来源:尧图企业网站定制
Flutter Provider 状态管理完全指南引言Provider 是 Flutter 中最流行的状态管理方案之一它基于 InheritedWidget 实现提供了简单而强大的状态管理方式。本文将深入探讨 Provider 的各种用法和高级技巧。基础概念回顾Provider 类型Provider- 最基础的提供者ChangeNotifierProvider- 用于 ChangeNotifierFutureProvider- 用于异步操作StreamProvider- 用于流数据MultiProvider- 多个提供者组合Consumer 模式ConsumerMyModel( builder: (context, model, child) { return Text(model.value.toString()); }, )高级技巧一ChangeNotifier创建模型class Counter extends ChangeNotifier { int _count 0; int get count _count; void increment() { _count; notifyListeners(); } void decrement() { _count--; notifyListeners(); } void reset() { _count 0; notifyListeners(); } }注册 Providervoid main() { runApp( ChangeNotifierProvider( create: (context) Counter(), child: MyApp(), ), ); }消费数据class CounterWidget extends StatelessWidget { override Widget build(BuildContext context) { return ConsumerCounter( builder: (context, counter, child) { return Column( children: [ Text(Count: ${counter.count}), ElevatedButton( onPressed: counter.increment, child: Text(Increment), ), ], ); }, ); } }高级技巧二Selector选择特定数据SelectorCounter, int( selector: (context, counter) counter.count, builder: (context, count, child) { return Text(Count: $count); }, )多个选择器Selector2Counter, ThemeMode, String( selector: (context, counter, theme) { return ${counter.count} - ${theme.name}; }, builder: (context, value, child) { return Text(value); }, )高级技巧三FutureProvider基本用法FutureProviderString( create: (context) async { await Future.delayed(Duration(seconds: 2)); return Loaded data; }, initialData: Loading..., builder: (context, child) { final data context.watchString(); return Text(data); }, )处理错误FutureProviderString( create: (context) async { throw Exception(Error); }, catchError: (context, error) Error: $error, builder: (context, child) { final data context.watchString(); return Text(data); }, )高级技巧四StreamProvider基本用法StreamProviderint( create: (context) Stream.periodic( Duration(seconds: 1), (i) i, ), initialData: 0, builder: (context, child) { final count context.watchint(); return Text(Count: $count); }, )处理流错误StreamProviderint( create: (context) errorStream, initialData: 0, catchError: (context, error) -1, builder: (context, child) { final count context.watchint(); return count -1 ? Text(Error occurred) : Text(Count: $count); }, )高级技巧五MultiProvider组合多个 ProviderMultiProvider( providers: [ ChangeNotifierProvider(create: (context) Counter()), ChangeNotifierProvider(create: (context) ThemeManager()), FutureProvider(create: (context) fetchUser()), ], child: MyApp(), )实战案例用户认证状态管理AuthProviderclass AuthProvider extends ChangeNotifier { User? _user; bool _isLoading false; String? _error; User? get user _user; bool get isLoading _isLoading; String? get error _error; bool get isAuthenticated _user ! null; Futurevoid login(String email, String password) async { _isLoading true; _error null; notifyListeners(); try { final user await authService.login(email, password); _user user; } catch (e) { _error e.toString(); } finally { _isLoading false; notifyListeners(); } } Futurevoid logout() async { await authService.logout(); _user null; notifyListeners(); } }登录页面class LoginPage extends StatelessWidget { final _emailController TextEditingController(); final _passwordController TextEditingController(); override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(Login)), body: ConsumerAuthProvider( builder: (context, auth, child) { if (auth.isLoading) { return Center(child: CircularProgressIndicator()); } return Padding( padding: EdgeInsets.all(16), child: Column( children: [ if (auth.error ! null) Text(auth.error!, style: TextStyle(color: Colors.red)), TextField( controller: _emailController, decoration: InputDecoration(labelText: Email), keyboardType: TextInputType.emailAddress, ), TextField( controller: _passwordController, decoration: InputDecoration(labelText: Password), obscureText: true, ), ElevatedButton( onPressed: () { auth.login( _emailController.text, _passwordController.text, ); }, child: Text(Login), ), ], ), ); }, ), ); } }实战案例主题切换ThemeProviderclass ThemeProvider extends ChangeNotifier { ThemeMode _themeMode ThemeMode.system; ThemeMode get themeMode _themeMode; void toggleTheme() { switch (_themeMode) { case ThemeMode.light: _themeMode ThemeMode.dark; break; case ThemeMode.dark: _themeMode ThemeMode.system; break; case ThemeMode.system: _themeMode ThemeMode.light; break; } notifyListeners(); } ThemeData get themeData { switch (_themeMode) { case ThemeMode.light: return ThemeData.light(); case ThemeMode.dark: return ThemeData.dark(); case ThemeMode.system: default: return MediaQuery.platformBrightnessOf(context) Brightness.dark ? ThemeData.dark() : ThemeData.light(); } } }主题切换按钮class ThemeToggleButton extends StatelessWidget { override Widget build(BuildContext context) { return ConsumerThemeProvider( builder: (context, themeProvider, child) { return IconButton( icon: Icon( themeProvider.themeMode ThemeMode.dark ? Icons.light_mode : Icons.dark_mode, ), onPressed: themeProvider.toggleTheme, ); }, ); } }实战案例购物车管理CartProviderclass CartProvider extends ChangeNotifier { final ListCartItem _items []; ListCartItem get items _items; double get total { return _items.fold(0, (sum, item) sum item.price * item.quantity); } int get itemCount { return _items.fold(0, (sum, item) sum item.quantity); } void addItem(Product product) { final existingItem _items.firstWhere( (item) item.product.id product.id, orElse: () CartItem(product: product, quantity: 0), ); if (existingItem.quantity 0) { _items.add(CartItem(product: product, quantity: 1)); } else { existingItem.quantity; } notifyListeners(); } void removeItem(Product product) { final index _items.indexWhere((item) item.product.id product.id); if (index ! -1) { if (_items[index].quantity 1) { _items[index].quantity--; } else { _items.removeAt(index); } notifyListeners(); } } void clearCart() { _items.clear(); notifyListeners(); } } class CartItem { final Product product; int quantity; CartItem({required this.product, required this.quantity}); double get price product.price; }购物车图标class CartIcon extends StatelessWidget { override Widget build(BuildContext context) { return ConsumerCartProvider( builder: (context, cart, child) { return Stack( children: [ IconButton( icon: Icon(Icons.shopping_cart), onPressed: () Navigator.pushNamed(context, /cart), ), if (cart.itemCount 0) Positioned( right: 0, top: 0, child: Container( padding: EdgeInsets.all(2), decoration: BoxDecoration( color: Colors.red, borderRadius: BorderRadius.circular(10), ), constraints: BoxConstraints( minWidth: 20, minHeight: 20, ), child: Text( cart.itemCount.toString(), style: TextStyle( fontSize: 12, color: Colors.white, ), textAlign: TextAlign.center, ), ), ), ], ); }, ); } }常见问题与解决方案Q1如何获取 Provider 但不重建A使用listen: falsefinal counter Provider.ofCounter(context, listen: false);Q2如何在 initState 中使用 ProviderA使用listen: falseoverride void initState() { super.initState(); final counter Provider.ofCounter(context, listen: false); counter.increment(); }Q3如何传递参数给 ProviderA使用create函数ChangeNotifierProvider( create: (context) MyModel(initialValue: 42), child: MyWidget(), )最佳实践1. 使用 Consumer 而非 Provider.of// 推荐 ConsumerCounter( builder: (context, counter, child) { return Text(${counter.count}); }, ) // 不推荐 Provider.ofCounter(context).count2. 拆分 Provider// 推荐按功能拆分 MultiProvider( providers: [ ChangeNotifierProvider(create: (context) AuthProvider()), ChangeNotifierProvider(create: (context) CartProvider()), ChangeNotifierProvider(create: (context) ThemeProvider()), ], ) // 不推荐单一大 Provider ChangeNotifierProvider(create: (context) AppState())3. 使用 Selector 优化性能// 推荐只监听需要的数据 SelectorCounter, int( selector: (context, counter) counter.count, builder: (context, count, child) { return Text(Count: $count); }, ) // 不推荐监听整个对象 ConsumerCounter( builder: (context, counter, child) { return Text(Count: ${counter.count}); }, )总结Provider 是 Flutter 中简单而强大的状态管理方案。通过本文的学习你应该能够使用 ChangeNotifier 创建可观察模型使用各种 Provider 类型使用 Consumer 和 Selector 消费数据实现复杂的状态管理场景优化性能掌握这些技巧能够帮助你构建更加健壮和可维护的 Flutter 应用。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价