Flutter 状态管理:从 Provider 到 Riverpod

张开发
2026/4/7 19:39:18 15 分钟阅读

分享文章

Flutter 状态管理:从 Provider 到 Riverpod
Flutter 状态管理从 Provider 到 Riverpod掌握 Flutter 状态管理的核心概念和最佳实践。一、状态管理的重要性作为一名追求像素级还原的 UI 匠人我深知良好的状态管理对于构建高质量 Flutter 应用的重要性。状态管理不仅影响应用的性能还直接关系到代码的可维护性和可扩展性。从简单的 setState 到复杂的状态管理库Flutter 提供了多种状态管理方案每种方案都有其适用场景。二、基础状态管理1. setStateclass CounterApp extends StatefulWidget { override _CounterAppState createState() _CounterAppState(); } class _CounterAppState extends StateCounterApp { int _count 0; void _incrementCounter() { setState(() { _count; }); } override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(计数器)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(点击次数$_count), SizedBox(height: 20), ElevatedButton( onPressed: _incrementCounter, child: Text(增加), ), ], ), ), ); } }2. InheritedWidgetclass AppState extends InheritedWidget { final int count; final Function() increment; AppState({ Key? key, required this.count, required this.increment, required Widget child, }) : super(key: key, child: child); static AppState of(BuildContext context) { final AppState? result context.dependOnInheritedWidgetOfExactTypeAppState(); assert(result ! null, No AppState found in context); return result!; } override bool updateShouldNotify(AppState oldWidget) { return count ! oldWidget.count; } } class InheritedWidgetExample extends StatefulWidget { override _InheritedWidgetExampleState createState() _InheritedWidgetExampleState(); } class _InheritedWidgetExampleState extends StateInheritedWidgetExample { int _count 0; void _increment() { setState(() { _count; }); } override Widget build(BuildContext context) { return AppState( count: _count, increment: _increment, child: Scaffold( appBar: AppBar(title: Text(InheritedWidget 示例)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ CounterDisplay(), SizedBox(height: 20), CounterButton(), ], ), ), ), ); } } class CounterDisplay extends StatelessWidget { override Widget build(BuildContext context) { final appState AppState.of(context); return Text(点击次数${appState.count}); } } class CounterButton extends StatelessWidget { override Widget build(BuildContext context) { final appState AppState.of(context); return ElevatedButton( onPressed: appState.increment, child: Text(增加), ); } }三、Provider1. 基本使用import package:flutter/material.dart; import package:provider/provider.dart; class Counter with ChangeNotifier { int _count 0; int get count _count; void increment() { _count; notifyListeners(); } } class ProviderExample extends StatelessWidget { override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (context) Counter(), child: Scaffold( appBar: AppBar(title: Text(Provider 示例)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ConsumerCounter( builder: (context, counter, child) { return Text(点击次数${counter.count}); }, ), SizedBox(height: 20), ConsumerCounter( builder: (context, counter, child) { return ElevatedButton( onPressed: counter.increment, child: Text(增加), ); }, ), ], ), ), ), ); } }2. 多 Providerclass User with ChangeNotifier { String _name 张三; String get name _name; void updateName(String newName) { _name newName; notifyListeners(); } } class MultiProviderExample extends StatelessWidget { override Widget build(BuildContext context) { return MultiProvider( providers: [ ChangeNotifierProvider(create: (context) Counter()), ChangeNotifierProvider(create: (context) User()), ], child: Scaffold( appBar: AppBar(title: Text(MultiProvider 示例)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ConsumerUser( builder: (context, user, child) { return Text(用户名${user.name}); }, ), SizedBox(height: 10), ConsumerCounter( builder: (context, counter, child) { return Text(点击次数${counter.count}); }, ), SizedBox(height: 20), ConsumerCounter( builder: (context, counter, child) { return ElevatedButton( onPressed: counter.increment, child: Text(增加计数), ); }, ), SizedBox(height: 10), ConsumerUser( builder: (context, user, child) { return ElevatedButton( onPressed: () user.updateName(李四), child: Text(更新用户名), ); }, ), ], ), ), ), ); } }四、Riverpod1. 基本使用import package:flutter/material.dart; import package:flutter_riverpod/flutter_riverpod.dart; final counterProvider StateProvider((ref) 0); class RiverpodExample extends StatelessWidget { override Widget build(BuildContext context) { return ProviderScope( child: Scaffold( appBar: AppBar(title: Text(Riverpod 示例)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Consumer( builder: (context, ref, child) { final count ref.watch(counterProvider); return Text(点击次数$count); }, ), SizedBox(height: 20), Consumer( builder: (context, ref, child) { return ElevatedButton( onPressed: () { ref.read(counterProvider.state).state; }, child: Text(增加), ); }, ), ], ), ), ), ); } }2. 自定义 Providerfinal userProvider StateNotifierProviderUserNotifier, User((ref) { return UserNotifier(); }); class User { final String name; final int age; User({required this.name, required this.age}); } class UserNotifier extends StateNotifierUser { UserNotifier() : super(User(name: 张三, age: 20)); void updateName(String newName) { state User(name: newName, age: state.age); } void updateAge(int newAge) { state User(name: state.name, age: newAge); } } class CustomProviderExample extends StatelessWidget { override Widget build(BuildContext context) { return ProviderScope( child: Scaffold( appBar: AppBar(title: Text(自定义 Provider 示例)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Consumer( builder: (context, ref, child) { final user ref.watch(userProvider); return Column( children: [ Text(用户名${user.name}), Text(年龄${user.age}), ], ); }, ), SizedBox(height: 20), Consumer( builder: (context, ref, child) { return ElevatedButton( onPressed: () { ref.read(userProvider.notifier).updateName(李四); }, child: Text(更新用户名), ); }, ), SizedBox(height: 10), Consumer( builder: (context, ref, child) { return ElevatedButton( onPressed: () { ref.read(userProvider.notifier).updateAge(25); }, child: Text(更新年龄), ); }, ), ], ), ), ), ); } }五、状态管理最佳实践根据复杂度选择方案简单状态setState中等复杂度Provider复杂状态Riverpod状态分层局部状态使用 setState组件树状态使用 Provider全局状态使用 Riverpod性能优化使用 const 构造器合理使用 Consumer避免不必要的重建代码组织将状态逻辑与 UI 分离使用服务层处理业务逻辑保持 Provider 简洁六、实战案例// 完整的 Riverpod 示例 final todosProvider StateNotifierProviderTodosNotifier, ListTodo((ref) { return TodosNotifier(); }); class Todo { final String id; final String title; final bool completed; Todo({required this.id, required this.title, this.completed false}); Todo copyWith({String? id, String? title, bool? completed}) { return Todo( id: id ?? this.id, title: title ?? this.title, completed: completed ?? this.completed, ); } } class TodosNotifier extends StateNotifierListTodo { TodosNotifier() : super([]); void addTodo(String title) { final newTodo Todo( id: DateTime.now().toString(), title: title, ); state [...state, newTodo]; } void toggleTodo(String id) { state state.map((todo) { if (todo.id id) { return todo.copyWith(completed: !todo.completed); } return todo; }).toList(); } void removeTodo(String id) { state state.where((todo) todo.id ! id).toList(); } } class TodoApp extends StatelessWidget { override Widget build(BuildContext context) { return ProviderScope( child: Scaffold( appBar: AppBar(title: Text(待办事项)), body: Consumer( builder: (context, ref, child) { final todos ref.watch(todosProvider); return ListView.builder( itemCount: todos.length, itemBuilder: (context, index) { final todo todos[index]; return ListTile( title: Text( todo.title, style: TextStyle( decoration: todo.completed ? TextDecoration.lineThrough : null, ), ), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ Checkbox( value: todo.completed, onChanged: (_) { ref.read(todosProvider.notifier).toggleTodo(todo.id); }, ), IconButton( icon: Icon(Icons.delete), onPressed: () { ref.read(todosProvider.notifier).removeTodo(todo.id); }, ), ], ), ); }, ); }, ), floatingActionButton: FloatingActionButton( onPressed: () { // 显示添加待办事项的对话框 showDialog( context: context, builder: (context) { final controller TextEditingController(); return AlertDialog( title: Text(添加待办事项), content: TextField( controller: controller, decoration: InputDecoration(hintText: 输入待办事项), ), actions: [ TextButton( onPressed: () Navigator.pop(context), child: Text(取消), ), TextButton( onPressed: () { if (controller.text.isNotEmpty) { context.read(todosProvider.notifier).addTodo(controller.text); Navigator.pop(context); } }, child: Text(添加), ), ], ); }, ); }, child: Icon(Icons.add), ), ), ); } }七、总结状态管理是 Flutter 开发中的核心概念选择合适的状态管理方案对于构建高质量的应用至关重要。从简单的 setState 到强大的 Riverpod每种方案都有其适用场景。作为一名 UI 匠人我建议根据应用的复杂度和团队的熟悉程度选择合适的状态管理方案以确保代码的可维护性和可扩展性。好的状态管理是构建高质量 Flutter 应用的基石。#flutter #state-management #provider #riverpod #dart

更多文章