Flutter状态管理进阶

张开发
2026/4/13 1:12:15 15 分钟阅读

分享文章

Flutter状态管理进阶
Flutter状态管理进阶1. 前言状态管理是Flutter应用开发中的核心概念它决定了如何管理和更新应用的状态。本文将深入探讨Flutter中的高级状态管理技巧帮助你创建更加可维护、可扩展的应用。2. 状态管理基础2.1 setStateclass Counter extends StatefulWidget { override _CounterState createState() _CounterState(); } class _CounterState extends StateCounter { int _counter 0; void _increment() { setState(() { _counter; }); } override Widget build(BuildContext context) { return Column( children: [ Text(Counter: $_counter), ElevatedButton( onPressed: _increment, child: Text(Increment), ), ], ); } }2.2 ValueNotifierclass Counter extends StatefulWidget { override _CounterState createState() _CounterState(); } class _CounterState extends StateCounter { final _counter ValueNotifierint(0); void _increment() { _counter.value; } override Widget build(BuildContext context) { return Column( children: [ ValueListenableBuilderint( valueListenable: _counter, builder: (context, value, child) { return Text(Counter: $value); }, ), ElevatedButton( onPressed: _increment, child: Text(Increment), ), ], ); } }3. Provider3.1 基础用法dependencies: flutter: sdk: flutter provider: ^6.0.5class CounterModel extends ChangeNotifier { int _count 0; int get count _count; void increment() { _count; notifyListeners(); } } class CounterApp extends StatelessWidget { override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (context) CounterModel(), child: MaterialApp( home: CounterScreen(), ), ); } } class CounterScreen extends StatelessWidget { override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(Counter)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ConsumerCounterModel( builder: (context, counter, child) { return Text(Counter: ${counter.count}); }, ), ElevatedButton( onPressed: () { Provider.ofCounterModel(context, listen: false).increment(); }, child: Text(Increment), ), ], ), ), ); } }3.2 多个Providerclass CounterModel extends ChangeNotifier { int _count 0; int get count _count; void increment() { _count; notifyListeners(); } } class UserModel extends ChangeNotifier { String _name John; String get name _name; void setName(String name) { _name name; notifyListeners(); } } class MyApp extends StatelessWidget { override Widget build(BuildContext context) { return MultiProvider( providers: [ ChangeNotifierProvider(create: (context) CounterModel()), ChangeNotifierProvider(create: (context) UserModel()), ], child: MaterialApp( home: HomeScreen(), ), ); } } class HomeScreen extends StatelessWidget { override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(Home)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ConsumerCounterModel( builder: (context, counter, child) { return Text(Counter: ${counter.count}); }, ), ConsumerUserModel( builder: (context, user, child) { return Text(User: ${user.name}); }, ), ElevatedButton( onPressed: () { Provider.ofCounterModel(context, listen: false).increment(); }, child: Text(Increment Counter), ), ElevatedButton( onPressed: () { Provider.ofUserModel(context, listen: false).setName(Jane); }, child: Text(Change User), ), ], ), ), ); } }3.3 嵌套Providerclass AppModel extends ChangeNotifier { String _appName My App; String get appName _appName; } class UserModel extends ChangeNotifier { String _name John; String get name _name; void setName(String name) { _name name; notifyListeners(); } } class MyApp extends StatelessWidget { override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (context) AppModel(), child: MaterialApp( home: ChangeNotifierProvider( create: (context) UserModel(), child: HomeScreen(), ), ), ); } } class HomeScreen extends StatelessWidget { override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: ConsumerAppModel( builder: (context, app, child) { return Text(app.appName); }, ), ), body: Center( child: ConsumerUserModel( builder: (context, user, child) { return Text(User: ${user.name}); }, ), ), ); } }4. Riverpod4.1 基础用法dependencies: flutter: sdk: flutter riverpod: ^2.0.2final counterProvider StateProviderint((ref) 0); class CounterApp extends StatelessWidget { override Widget build(BuildContext context) { return ProviderScope( child: MaterialApp( home: CounterScreen(), ), ); } } class CounterScreen extends ConsumerWidget { override Widget build(BuildContext context, WidgetRef ref) { final counter ref.watch(counterProvider); return Scaffold( appBar: AppBar(title: Text(Counter)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(Counter: $counter), ElevatedButton( onPressed: () { ref.read(counterProvider.notifier).state; }, child: Text(Increment), ), ], ), ), ); } }4.2 状态管理class User { final String name; final int age; User({required this.name, required this.age}); } final userProvider StateNotifierProviderUserNotifier, User((ref) { return UserNotifier(); }); class UserNotifier extends StateNotifierUser { UserNotifier() : super(User(name: John, age: 30)); void updateName(String name) { state User(name: name, age: state.age); } void updateAge(int age) { state User(name: state.name, age: age); } } class UserScreen extends ConsumerWidget { override Widget build(BuildContext context, WidgetRef ref) { final user ref.watch(userProvider); return Scaffold( appBar: AppBar(title: Text(User)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(Name: ${user.name}), Text(Age: ${user.age}), ElevatedButton( onPressed: () { ref.read(userProvider.notifier).updateName(Jane); }, child: Text(Change Name), ), ElevatedButton( onPressed: () { ref.read(userProvider.notifier).updateAge(25); }, child: Text(Change Age), ), ], ), ), ); } }4.3 依赖注入final apiProvider ProviderApi((ref) Api()); final userProvider FutureProviderUser((ref) async { final api ref.watch(apiProvider); return await api.fetchUser(); }); class Api { FutureUser fetchUser() async { // 模拟网络请求 await Future.delayed(Duration(seconds: 1)); return User(name: John, age: 30); } } class UserScreen extends ConsumerWidget { override Widget build(BuildContext context, WidgetRef ref) { final user ref.watch(userProvider); return Scaffold( appBar: AppBar(title: Text(User)), body: user.when( data: (user) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(Name: ${user.name}), Text(Age: ${user.age}), ], ), ); }, loading: () Center(child: CircularProgressIndicator()), error: (error, stack) Center(child: Text(Error: $error)), ), ); } }5. Bloc5.1 基础用法dependencies: flutter: sdk: flutter flutter_bloc: ^8.1.3 equatable: ^2.0.5// Events abstract class CounterEvent extends Equatable { override ListObject get props []; } class IncrementEvent extends CounterEvent {} class DecrementEvent extends CounterEvent {} // States class CounterState extends Equatable { final int count; CounterState(this.count); override ListObject get props [count]; } // Bloc class CounterBloc extends BlocCounterEvent, CounterState { CounterBloc() : super(CounterState(0)) { onIncrementEvent((event, emit) { emit(CounterState(state.count 1)); }); onDecrementEvent((event, emit) { emit(CounterState(state.count - 1)); }); } } // UI class CounterScreen extends StatelessWidget { override Widget build(BuildContext context) { return BlocProvider( create: (context) CounterBloc(), child: CounterView(), ); } } class CounterView extends StatelessWidget { override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(Counter)), body: BlocBuilderCounterBloc, CounterState( builder: (context, state) { return Center( child: Text(Counter: ${state.count}), ); }, ), floatingActionButton: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ FloatingActionButton( onPressed: () { context.readCounterBloc().add(IncrementEvent()); }, child: Icon(Icons.add), ), SizedBox(height: 10), FloatingActionButton( onPressed: () { context.readCounterBloc().add(DecrementEvent()); }, child: Icon(Icons.remove), ), ], ), ); } }5.2 复杂状态管理// Events abstract class UserEvent extends Equatable { override ListObject get props []; } class FetchUserEvent extends UserEvent {} class UpdateUserEvent extends UserEvent { final String name; final int age; UpdateUserEvent(this.name, this.age); override ListObject get props [name, age]; } // States abstract class UserState extends Equatable { override ListObject get props []; } class UserInitialState extends UserState {} class UserLoadingState extends UserState {} class UserLoadedState extends UserState { final User user; UserLoadedState(this.user); override ListObject get props [user]; } class UserErrorState extends UserState { final String error; UserErrorState(this.error); override ListObject get props [error]; } // Bloc class UserBloc extends BlocUserEvent, UserState { final Api api; UserBloc(this.api) : super(UserInitialState()) { onFetchUserEvent((event, emit) async { emit(UserLoadingState()); try { final user await api.fetchUser(); emit(UserLoadedState(user)); } catch (e) { emit(UserErrorState(Failed to fetch user)); } }); onUpdateUserEvent((event, emit) async { emit(UserLoadingState()); try { final user await api.updateUser(event.name, event.age); emit(UserLoadedState(user)); } catch (e) { emit(UserErrorState(Failed to update user)); } }); } } // UI class UserScreen extends StatelessWidget { override Widget build(BuildContext context) { return BlocProvider( create: (context) UserBloc(Api()), child: UserView(), ); } } class UserView extends StatelessWidget { override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(User)), body: BlocBuilderUserBloc, UserState( builder: (context, state) { if (state is UserInitialState) { return Center( child: ElevatedButton( onPressed: () { context.readUserBloc().add(FetchUserEvent()); }, child: Text(Fetch User), ), ); } else if (state is UserLoadingState) { return Center(child: CircularProgressIndicator()); } else if (state is UserLoadedState) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(Name: ${state.user.name}), Text(Age: ${state.user.age}), ElevatedButton( onPressed: () { context.readUserBloc().add(UpdateUserEvent(Jane, 25)); }, child: Text(Update User), ), ], ), ); } else if (state is UserErrorState) { return Center(child: Text(state.error)); } return Container(); }, ), ); } }6. GetX6.1 基础用法dependencies: flutter: sdk: flutter get: ^4.6.5class CounterController extends GetxController { var count 0.obs; void increment() { count; } void decrement() { count--; } } class CounterScreen extends StatelessWidget { final controller Get.put(CounterController()); override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(Counter)), body: Center( child: Obx(() { return Text(Counter: ${controller.count}); }), ), floatingActionButton: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ FloatingActionButton( onPressed: controller.increment, child: Icon(Icons.add), ), SizedBox(height: 10), FloatingActionButton( onPressed: controller.decrement, child: Icon(Icons.remove), ), ], ), ); } }6.2 导航与状态管理class HomeController extends GetxController { var count 0.obs; void increment() { count; } void navigateToDetail() { Get.to(DetailScreen(), arguments: count.value); } } class DetailController extends GetxController { var count 0.obs; override void onInit() { super.onInit(); final arguments Get.arguments; if (arguments ! null) { count.value arguments; } } void increment() { count; } void navigateBack() { Get.back(result: count.value); } } class HomeScreen extends StatelessWidget { final controller Get.put(HomeController()); override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(Home)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Obx(() { return Text(Counter: ${controller.count}); }), ElevatedButton( onPressed: controller.increment, child: Text(Increment), ), ElevatedButton( onPressed: controller.navigateToDetail, child: Text(Go to Detail), ), ], ), ), ); } } class DetailScreen extends StatelessWidget { final controller Get.put(DetailController()); override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(Detail)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Obx(() { return Text(Counter: ${controller.count}); }), ElevatedButton( onPressed: controller.increment, child: Text(Increment), ), ElevatedButton( onPressed: controller.navigateBack, child: Text(Go Back), ), ], ), ), ); } }7. 状态管理选择7.1 选择依据简单应用setState、ValueNotifier中小型应用Provider、Riverpod复杂应用Bloc、GetX7.2 性能考量Provider简单性能好Riverpod功能强大性能好Bloc可预测性能一般GetX功能丰富性能好8. 最佳实践8.1 状态管理原则单一数据源所有状态来自一个源头不可变性状态更新时创建新状态可预测性状态变化可追踪可测试性状态逻辑易于测试8.2 代码组织状态分离将状态与UI分离逻辑分离将业务逻辑与UI逻辑分离模块化将状态管理按功能模块组织8.3 性能优化避免不必要的重建使用const构造函数合理使用监听只监听必要的状态批量更新合并多个状态更新9. 实际应用案例9.1 登录功能class AuthController extends GetxController { var isLoading false.obs; var error .obs; var user RxnUser(); Futurevoid login(String email, String password) async { isLoading.value true; error.value ; try { // 模拟登录请求 await Future.delayed(Duration(seconds: 2)); user.value User(id: 1, name: John, email: email); Get.offAll(HomeScreen()); } catch (e) { error.value Login failed; } finally { isLoading.value false; } } void logout() { user.value null; Get.offAll(LoginScreen()); } } class LoginScreen extends StatelessWidget { final controller Get.put(AuthController()); final emailController TextEditingController(); final passwordController TextEditingController(); override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(Login)), body: Padding( padding: EdgeInsets.all(20), child: Column( children: [ TextField( controller: emailController, decoration: InputDecoration(labelText: Email), ), TextField( controller: passwordController, decoration: InputDecoration(labelText: Password), obscureText: true, ), Obx(() { return Text(controller.error.value, style: TextStyle(color: Colors.red)); }), Obx(() { return ElevatedButton( onPressed: controller.isLoading.value ? null : () { controller.login(emailController.text, passwordController.text); }, child: controller.isLoading.value ? CircularProgressIndicator() : Text(Login), ); }), ], ), ), ); } }9.2 购物车功能class CartController extends GetxController { var items CartItem[].obs; double get total items.fold(0, (sum, item) sum item.price * item.quantity); void addItem(Product product) { final existingItem items.firstWhereOrNull((item) item.product.id product.id); if (existingItem ! null) { existingItem.quantity; } else { items.add(CartItem(product: product, quantity: 1)); } } void removeItem(CartItem item) { if (item.quantity 1) { item.quantity--; } else { items.remove(item); } } void clearCart() { items.clear(); } } class CartScreen extends StatelessWidget { final controller Get.put(CartController()); override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(Cart)), body: Obx(() { if (controller.items.isEmpty) { return Center(child: Text(Cart is empty)); } return ListView.builder( itemCount: controller.items.length, itemBuilder: (context, index) { final item controller.items[index]; return ListTile( title: Text(item.product.name), subtitle: Text(\$${item.price} x ${item.quantity}), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( onPressed: () controller.removeItem(item), icon: Icon(Icons.remove), ), IconButton( onPressed: () controller.addItem(item.product), icon: Icon(Icons.add), ), ], ), ); }, ); }), bottomNavigationBar: Obx(() { if (controller.items.isEmpty) return null; return Container( padding: EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text(Total: \$${controller.total.toStringAsFixed(2)}), ElevatedButton( onPressed: () {}, child: Text(Checkout), ), ], ), ); }), ); } }10. 常见问题与解决方案10.1 状态管理混乱问题状态管理逻辑混乱难以维护解决方案按功能模块组织状态使用合适的状态管理方案10.2 性能问题问题状态更新导致不必要的重建解决方案使用const构造函数合理使用监听10.3 状态共享问题跨组件状态共享困难解决方案使用全局状态管理方案如Provider、Riverpod11. 总结Flutter提供了多种状态管理方案从简单的setState到复杂的Bloc每种方案都有其适用场景。通过本文介绍的技巧你可以选择合适的状态管理方案并应用最佳实践创建更加可维护、可扩展的应用。记住好的状态管理应该是清晰、可预测、易于测试的。希望本文对你有所帮助祝你在Flutter状态管理的世界中创造出更加精彩的应用

更多文章