Flutter第三方状态管理包全面指南
状态管理是Flutter应用开发中的核心挑战。以下是目前最流行的第三方状态管理包及其详细使用指南。
1. Provider (官方推荐)
简介
Provider是Flutter官方推荐的轻量级状态管理方案,基于InheritedWidget实现。
安装
yaml
dependencies:
provider: ^6.0.5
基础用法
dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
// 1. 创建Model类
class CounterModel extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners(); // 通知监听者状态已改变
}
void decrement() {
_count--;
notifyListeners();
}
}
// 2. 在顶层提供Model
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => CounterModel()),
// 可以添加更多Provider
],
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Provider示例',
home: HomePage(),
);
}
}
// 3. 消费状态 - 方式一:Consumer
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Provider示例')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('当前计数:'),
Consumer<CounterModel>(
builder: (context, counter, child) {
return Text(
'${counter.count}',
style: TextStyle(fontSize: 48, fontWeight: FontWeight.bold),
);
},
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
context.read<CounterModel>().decrement();
},
child: Icon(Icons.remove),
),
SizedBox(width: 20),
ElevatedButton(
onPressed: () {
context.read<CounterModel>().increment();
},
child: Icon(Icons.add),
),
],
),
],
),
),
);
}
}
// 4. 消费状态 - 方式二:使用Provider.of
class CounterDisplay extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 监听状态变化,当状态改变时重建Widget
final counter = Provider.of<CounterModel>(context);
return Text('计数: ${counter.count}');
}
}
// 5. 消费状态 - 方式三:使用context.watch/context.read
class CounterDisplay2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
// watch:监听变化
final counter = context.watch<CounterModel>();
return Text('计数: ${counter.count}');
}
}
class CounterButtons extends StatelessWidget {
@override
Widget build(BuildContext context) {
// read:只读取一次,不监听变化
return Row(
children: [
ElevatedButton(
onPressed: () => context.read<CounterModel>().decrement(),
child: Text('减少'),
),
ElevatedButton(
onPressed: () => context.read<CounterModel>().increment(),
child: Text('增加'),
),
],
);
}
}
// 6. 使用Selector优化性能
class OptimizedCounterDisplay extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Selector<CounterModel, int>(
selector: (context, counter) => counter.count,
builder: (context, count, child) {
// 只有当count改变时才会重建
return Text('优化后的计数: $count');
},
);
}
}
高级用法:多个Provider和依赖关系
dart
// 多个Model类
class UserModel extends ChangeNotifier {
String _name = '张三';
String get name => _name;
void updateName(String newName) {
_name = newName;
notifyListeners();
}
}
class ThemeModel extends ChangeNotifier {
bool _isDark = false;
bool get isDark => _isDark;
ThemeData get theme => _isDark ? ThemeData.dark() : ThemeData.light();
void toggleTheme() {
_isDark = !_isDark;
notifyListeners();
}
}
// 在顶层提供多个Model
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => CounterModel()),
ChangeNotifierProvider(create: (_) => UserModel()),
ChangeNotifierProvider(create: (_) => ThemeModel()),
],
child: MyApp(),
),
);
}
// 依赖注入示例
class AuthModel extends ChangeNotifier {
bool _isLoggedIn = false;
String? _token;
bool get isLoggedIn => _isLoggedIn;
String? get token => _token;
void login(String username, String password) {
// 模拟登录
_token = 'jwt_token_here';
_isLoggedIn = true;
notifyListeners();
}
void logout() {
_token = null;
_isLoggedIn = false;
notifyListeners();
}
}
class UserProfileModel extends ChangeNotifier {
UserProfile? _profile;
UserProfile? get profile => _profile;
Future<void> loadProfile(String token) async {
// 使用token加载用户信息
_profile = UserProfile(name: '张三', email: 'zhangsan@example.com');
notifyListeners();
}
}
// 使用ProxyProvider处理依赖
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => AuthModel()),
ProxyProvider<AuthModel, UserProfileModel>(
update: (context, auth, previous) {
return UserProfileModel()..loadProfile(auth.token ?? '');
},
),
],
child: MyApp(),
),
);
}
2. GetX
简介
GetX是一个功能全面的Flutter包,包含状态管理、路由管理和依赖注入。
安装
yaml
dependencies:
get: ^4.6.5
基础用法
dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
// 1. 创建Controller
class CounterController extends GetxController {
var count = 0.obs; // .obs 创建响应式变量
void increment() => count++;
void decrement() => count--;
// 计算属性
bool get isEven => count.value.isEven;
// 监听器
@override
void onInit() {
super.onInit();
// 监听count的变化
ever(count, (_) => print('Count changed: ${count.value}'));
}
}
// 2. 使用GetX状态管理
class CounterPage extends StatelessWidget {
// 注入Controller
final CounterController controller = Get.put(CounterController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('GetX状态管理')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 使用Obx监听变化
Obx(() => Text(
'Count: ${controller.count.value}',
style: TextStyle(fontSize: 48),
)),
Obx(() => Text(
'是否为偶数: ${controller.isEven ? "是" : "否"}',
style: TextStyle(fontSize: 20),
)),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: controller.decrement,
child: Icon(Icons.remove),
),
SizedBox(width: 20),
ElevatedButton(
onPressed: controller.increment,
child: Icon(Icons.add),
),
],
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// 跳转到另一个页面
Get.to(() => AnotherPage());
},
child: Text('跳转到另一个页面'),
),
],
),
),
);
}
}
// 3. 另一个页面,同样访问同一个Controller
class AnotherPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 获取已存在的Controller
final CounterController controller = Get.find<CounterController>();
return Scaffold(
appBar: AppBar(
title: Text('另一个页面'),
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => Get.back(),
),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Obx(() => Text(
'来自另一个页面的计数: ${controller.count.value}',
style: TextStyle(fontSize: 32),
)),
ElevatedButton(
onPressed: controller.increment,
child: Text('增加计数'),
),
],
),
),
);
}
}
// 4. 使用GetBuilder(不响应式)
class GetBuilderExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetBuilder<CounterController>(
init: CounterController(),
builder: (controller) {
return Column(
children: [
Text('使用GetBuilder: ${controller.count}'),
ElevatedButton(
onPressed: () {
controller.increment();
controller.update(); // 手动调用update
},
child: Text('增加'),
),
],
);
},
);
}
}
// 5. 使用GetX和Worker
class AdvancedController extends GetxController {
final name = ''.obs;
final email = ''.obs;
final isLoading = false.obs;
@override
void onInit() {
super.onInit();
// 监听name变化,防抖500ms
debounce(name, (_) {
print('Name changed: $name');
}, time: Duration(milliseconds: 500));
// 监听多个变量
everAll([name, email], (value) {
print('Name or Email changed');
});
// 条件监听
once(name, (value) {
print('Name第一次被设置: $value');
});
}
// 模拟API调用
void fetchData() async {
isLoading.value = true;
await Future.delayed(Duration(seconds: 2));
name.value = '李四';
email.value = 'lisi@example.com';
isLoading.value = false;
}
}
// 6. GetX依赖注入
class ApiService {
Future<void> fetchData() async {
await Future.delayed(Duration(seconds: 1));
}
}
class ProductController extends GetxController {
final ApiService apiService;
ProductController(this.apiService);
final products = <String>[].obs;
void loadProducts() async {
await apiService.fetchData();
products.addAll(['产品1', '产品2', '产品3']);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 全局依赖注入
Get.put(ApiService());
Get.put(ProductController(Get.find<ApiService>()));
return GetMaterialApp(
title: 'GetX示例',
home: CounterPage(),
);
}
}
3. Riverpod
简介
Riverpod是Provider的改进版本,解决了Provider的一些问题,提供更好的类型安全和可测试性。
安装
yaml
dependencies:
flutter_riverpod: ^2.3.6
riverpod_annotation: ^2.1.1
dev_dependencies:
build_runner: ^2.3.7
riverpod_generator: ^2.2.9
基础用法
dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'main.g.dart'; // 生成的代码
// 1. 使用代码生成创建Provider
@riverpod
int counter(CounterRef ref) {
return 0;
}
// 2. NotifierProvider示例
@riverpod
class CounterNotifier extends _$CounterNotifier {
@override
int build() {
return 0;
}
void increment() {
state++;
}
void decrement() {
state--;
}
}
// 3. FutureProvider示例
@riverpod
Future<String> userData(UserDataRef ref) async {
await Future.delayed(Duration(seconds: 1));
return '张三';
}
// 4. StreamProvider示例
@riverpod
Stream<int> timer(TimerRef ref) async* {
int seconds = 0;
while (true) {
await Future.delayed(Duration(seconds: 1));
yield seconds++;
}
}
// 5. 组合Provider
@riverpod
String greeting(GreetingRef ref) {
final userName = ref.watch(userDataProvider).value ?? '游客';
return '你好, $userName!';
}
// 6. 状态管理示例
@riverpod
class UserProfile extends _$UserProfile {
@override
UserProfileState build() {
return UserProfileState(
name: '',
email: '',
isLoading: false,
);
}
Future<void> loadProfile() async {
state = state.copyWith(isLoading: true);
await Future.delayed(Duration(seconds: 2));
state = state.copyWith(
name: '张三',
email: 'zhangsan@example.com',
isLoading: false,
);
}
void updateName(String newName) {
state = state.copyWith(name: newName);
}
}
// 状态类
class UserProfileState {
final String name;
final String email;
final bool isLoading;
UserProfileState({
required this.name,
required this.email,
required this.isLoading,
});
UserProfileState copyWith({
String? name,
String? email,
bool? isLoading,
}) {
return UserProfileState(
name: name ?? this.name,
email: email ?? this.email,
isLoading: isLoading ?? this.isLoading,
);
}
}
// 主应用
void main() {
runApp(
ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Riverpod示例',
home: HomePage(),
);
}
}
// 7. 使用ConsumerWidget
class HomePage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// 监听状态
final count = ref.watch(counterNotifierProvider);
final userProfile = ref.watch(userProfileProvider);
return Scaffold(
appBar: AppBar(title: Text('Riverpod示例')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('计数: $count', style: TextStyle(fontSize: 48)),
// 监听异步状态
ref.watch(userDataProvider).when(
data: (data) => Text('用户: $data'),
loading: () => CircularProgressIndicator(),
error: (err, stack) => Text('错误: $err'),
),
// 监听流
ref.watch(timerProvider).when(
data: (seconds) => Text('计时: $seconds秒'),
loading: () => CircularProgressIndicator(),
error: (err, stack) => Text('错误: $err'),
),
// 用户资料
if (userProfile.isLoading)
CircularProgressIndicator()
else
Column(
children: [
Text('姓名: ${userProfile.name}'),
Text('邮箱: ${userProfile.email}'),
],
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () => ref.read(counterNotifierProvider.notifier).increment(),
child: Text('增加'),
),
ElevatedButton(
onPressed: () => ref.read(userProfileProvider.notifier).loadProfile(),
child: Text('加载用户资料'),
),
],
),
),
);
}
}
// 8. 使用Consumer
class CounterDisplay extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer(
builder: (context, ref, child) {
final count = ref.watch(counterNotifierProvider);
return Text('计数: $count');
},
);
}
}
// 9. 使用StateNotifier
@riverpod
class TodoList extends _$TodoList {
@override
List<String> build() {
return [];
}
void add(String todo) {
state = [...state, todo];
}
void remove(int index) {
state = [...state]..removeAt(index);
}
void update(int index, String newTodo) {
state = [...state]..[index] = newTodo;
}
}
// 10. 使用Family
@riverpod
String todo(TodoRef ref, int id) {
// 根据id获取todo
return 'Todo $id';
}
// 使用
class TodoItem extends ConsumerWidget {
final int id;
TodoItem({required this.id});
@override
Widget build(BuildContext context, WidgetRef ref) {
final todo = ref.watch(todoProvider(id));
return Text(todo);
}
}
// 11. 使用Provider监听
class UserProfileWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// 监听用户资料变化
ref.listen<UserProfileState>(
userProfileProvider,
(previous, next) {
if (next.isLoading && !(previous?.isLoading ?? false)) {
// 开始加载
print('开始加载用户资料');
} else if (!next.isLoading && (previous?.isLoading ?? false)) {
// 加载完成
print('用户资料加载完成');
}
},
);
final userProfile = ref.watch(userProfileProvider);
// ...
}
}
4. BLoC (Cubit)
简介
BLoC是一种基于事件流的状态管理模式,Cubit是BLoC的简化版本。
安装
yaml
dependencies:
flutter_bloc: ^8.1.2
基础用法
dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
// 1. Cubit实现
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
void decrement() => emit(state - 1);
}
// 2. BLoC实现(基于事件)
// 定义事件
abstract class CounterEvent {}
class IncrementEvent extends CounterEvent {}
class DecrementEvent extends CounterEvent {}
class ResetEvent extends CounterEvent {}
// 定义状态
class CounterState {
final int count;
final bool isLoading;
CounterState({required this.count, this.isLoading = false});
CounterState copyWith({int? count, bool? isLoading}) {
return CounterState(
count: count ?? this.count,
isLoading: isLoading ?? this.isLoading,
);
}
}
// 实现BLoC
class CounterBloc extends Bloc<CounterEvent, CounterState> {
CounterBloc() : super(CounterState(count: 0)) {
on<IncrementEvent>(_onIncrement);
on<DecrementEvent>(_onDecrement);
on<ResetEvent>(_onReset);
}
void _onIncrement(IncrementEvent event, Emitter<CounterState> emit) {
emit(state.copyWith(count: state.count + 1));
}
void _onDecrement(DecrementEvent event, Emitter<CounterState> emit) {
emit(state.copyWith(count: state.count - 1));
}
void _onReset(ResetEvent event, Emitter<CounterState> emit) {
emit(state.copyWith(count: 0));
}
}
// 3. 使用Cubit
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Cubit示例')),
body: BlocProvider(
create: (context) => CounterCubit(),
child: CounterView(),
),
);
}
}
class CounterView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 使用BlocBuilder监听状态变化
BlocBuilder<CounterCubit, int>(
builder: (context, count) {
return Text(
'计数: $count',
style: TextStyle(fontSize: 48),
);
},
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () => context.read<CounterCubit>().decrement(),
child: Icon(Icons.remove),
),
SizedBox(width: 20),
ElevatedButton(
onPressed: () => context.read<CounterCubit>().increment(),
child: Icon(Icons.add),
),
],
),
],
),
);
}
}
// 4. 使用BLoC
class BlocCounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => CounterBloc(),
child: Scaffold(
appBar: AppBar(title: Text('BLoC示例')),
body: BlocBuilder<CounterBloc, CounterState>(
builder: (context, state) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (state.isLoading)
CircularProgressIndicator()
else
Text(
'计数: ${state.count}',
style: TextStyle(fontSize: 48),
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () => context.read<CounterBloc>().add(DecrementEvent()),
child: Icon(Icons.remove),
),
SizedBox(width: 20),
ElevatedButton(
onPressed: () => context.read<CounterBloc>().add(IncrementEvent()),
child: Icon(Icons.add),
),
SizedBox(width: 20),
ElevatedButton(
onPressed: () => context.read<CounterBloc>().add(ResetEvent()),
child: Text('重置'),
),
],
),
],
),
);
},
),
),
);
}
}
// 5. 监听事件
class CounterListener extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocListener<CounterBloc, CounterState>(
listener: (context, state) {
if (state.count == 10) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('计数达到10!')),
);
}
},
child: BlocBuilder<CounterBloc, CounterState>(
builder: (context, state) {
return Text('当前计数: ${state.count}');
},
),
);
}
}
// 6. 选择器优化性能
class CounterDisplay extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocSelector<CounterBloc, CounterState, int>(
selector: (state) => state.count,
builder: (context, count) {
// 只有当count改变时才会重建
return Text('计数: $count');
},
);
}
}
// 7. 异步操作示例
// 事件
abstract class UserEvent {}
class LoadUserEvent extends UserEvent {}
// 状态
class UserState {
final String? name;
final String? email;
final bool isLoading;
final String? error;
UserState({
this.name,
this.email,
this.isLoading = false,
this.error,
});
UserState copyWith({
String? name,
String? email,
bool? isLoading,
String? error,
}) {
return UserState(
name: name ?? this.name,
email: email ?? this.email,
isLoading: isLoading ?? this.isLoading,
error: error ?? this.error,
);
}
}
// BLoC
class UserBloc extends Bloc<UserEvent, UserState> {
UserBloc() : super(UserState()) {
on<LoadUserEvent>(_onLoadUser);
}
Future<void> _onLoadUser(LoadUserEvent event, Emitter<UserState> emit) async {
emit(state.copyWith(isLoading: true, error: null));
try {
await Future.delayed(Duration(seconds: 2));
// 模拟API调用
emit(state.copyWith(
name: '张三',
email: 'zhangsan@example.com',
isLoading: false,
));
} catch (e) {
emit(state.copyWith(
isLoading: false,
error: '加载失败: $e',
));
}
}
}
// 8. 使用Repository
class UserRepository {
Future<Map<String, dynamic>> fetchUser() async {
await Future.delayed(Duration(seconds: 2));
return {
'name': '李四',
'email': 'lisi@example.com',
};
}
}
// 9. 依赖注入
class MultiBlocPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider(create: (context) => CounterBloc()),
BlocProvider(create: (context) => UserBloc()),
],
child: Scaffold(
appBar: AppBar(title: Text('多BLoC示例')),
body: Column(
children: [
// Counter部分
BlocBuilder<CounterBloc, CounterState>(
builder: (context, state) {
return Text('计数: ${state.count}');
},
),
// User部分
BlocBuilder<UserBloc, UserState>(
builder: (context, state) {
if (state.isLoading) {
return CircularProgressIndicator();
} else if (state.error != null) {
return Text('错误: ${state.error}');
} else {
return Column(
children: [
Text('姓名: ${state.name}'),
Text('邮箱: ${state.email}'),
],
);
}
},
),
],
),
),
);
}
}
5. MobX
简介
MobX是一个响应式状态管理库,使用注解自动生成代码。
安装
yaml
dependencies:
mobx: ^2.1.4
flutter_mobx: ^2.0.7
dev_dependencies:
build_runner: ^2.3.7
mobx_codegen: ^2.1.3
基础用法
dart
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:mobx/mobx.dart';
part 'counter_store.g.dart'; // 生成的代码
// 1. 创建Store
class CounterStore = CounterStoreBase with _$CounterStore;
abstract class CounterStoreBase with Store {
@observable
int count = 0;
@observable
bool isLoading = false;
@computed
bool get isEven => count % 2 == 0;
@action
void increment() {
count++;
}
@action
void decrement() {
count--;
}
@action
Future<void> incrementAsync() async {
isLoading = true;
await Future.delayed(Duration(seconds: 1));
count++;
isLoading = false;
}
}
// 运行代码生成:flutter packages pub run build_runner build
// 2. 使用Observer
class CounterPage extends StatelessWidget {
final CounterStore store = CounterStore();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('MobX示例')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Observer(
builder: (_) => Text(
'计数: ${store.count}',
style: TextStyle(fontSize: 48),
),
),
Observer(
builder: (_) => Text(
'是否为偶数: ${store.isEven ? "是" : "否"}',
style: TextStyle(fontSize: 20),
),
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: store.decrement,
child: Icon(Icons.remove),
),
SizedBox(width: 20),
ElevatedButton(
onPressed: store.increment,
child: Icon(Icons.add),
),
],
),
SizedBox(height: 20),
Observer(
builder: (_) => ElevatedButton(
onPressed: store.isLoading ? null : store.incrementAsync,
child: store.isLoading
? CircularProgressIndicator()
: Text('异步增加'),
),
),
],
),
),
);
}
}
// 3. 复杂Store示例
class TodoStore = TodoStoreBase with _$TodoStore;
abstract class TodoStoreBase with Store {
@observable
ObservableList<String> todos = ObservableList.of([]);
@observable
String newTodo = '';
@computed
int get todoCount => todos.length;
@computed
bool get hasTodos => todos.isNotEmpty;
@action
void setNewTodo(String value) {
newTodo = value;
}
@action
void addTodo() {
if (newTodo.isNotEmpty) {
todos.add(newTodo);
newTodo = '';
}
}
@action
void removeTodo(int index) {
todos.removeAt(index);
}
@action
void clearTodos() {
todos.clear();
}
}
// 4. 使用Provider传递Store
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MobX示例',
home: Provider(
create: (_) => CounterStore(),
child: CounterPage(),
),
);
}
}
// 5. 在子Widget中获取Store
class CounterDisplay extends StatelessWidget {
@override
Widget build(BuildContext context) {
final store = Provider.of<CounterStore>(context);
return Observer(
builder: (_) => Text('计数: ${store.count}'),
);
}
}
6. 状态管理包对比
| 特性 | Provider | GetX | Riverpod | BLoC/Cubit | MobX |
|---|---|---|---|---|---|
| 学习曲线 | 简单 | 简单 | 中等 | 中等 | 中等 |
| 代码量 | 少 | 少 | 中等 | 多 | 中等 |
| 性能 | 好 | 好 | 优秀 | 好 | 好 |
| 类型安全 | 好 | 一般 | 优秀 | 优秀 | 优秀 |
| 代码生成 | 不需要 | 不需要 | 可选 | 不需要 | 需要 |
| 可测试性 | 好 | 好 | 优秀 | 优秀 | 好 |
| 社区支持 | 优秀 | 优秀 | 好 | 优秀 | 好 |
| 适合场景 | 中小项目 | 全功能需求 | 大型项目 | 大型复杂项目 | 响应式需求 |
7. 选择建议
- 新手/小型项目 :推荐 Provider,学习成本低,官方推荐
- 需要快速开发 :推荐 GetX,功能全面,开发效率高
- 大型/复杂项目 :推荐 Riverpod 或 BLoC,类型安全,可维护性好
- 需要强响应式 :推荐 MobX,响应式编程体验好
- 企业级应用 :推荐 Riverpod + BLoC,提供最佳的类型安全和架构
8. 最佳实践
1. 状态分离
dart
// 好的实践:状态分离
class AuthStore {
final isLoggedIn = false.obs;
final user = Rxn<User>();
final isLoading = false.obs;
}
class ProductStore {
final products = <Product>[].obs;
final selectedProduct = Rxn<Product>();
}
2. 使用Repository模式
dart
abstract class UserRepository {
Future<User> getUser(String id);
Future<void> updateUser(User user);
}
class UserRepositoryImpl implements UserRepository {
final ApiService api;
UserRepositoryImpl(this.api);
@override
Future<User> getUser(String id) async {
return await api.fetchUser(id);
}
@override
Future<void> updateUser(User user) async {
await api.updateUser(user);
}
}
3. 错误处理
dart
class DataState<T> {
final T? data;
final bool isLoading;
final String? error;
DataState({this.data, this.isLoading = false, this.error});
DataState<T> copyWith({T? data, bool? isLoading, String? error}) {
return DataState(
data: data ?? this.data,
isLoading: isLoading ?? this.isLoading,
error: error ?? this.error,
);
}
}
class DataStore<T> extends Cubit<DataState<T>> {
final Repository<T> repository;
DataStore(this.repository) : super(DataState());
Future<void> loadData() async {
emit(state.copyWith(isLoading: true, error: null));
try {
final data = await repository.fetch();
emit(state.copyWith(data: data, isLoading: false));
} catch (e) {
emit(state.copyWith(error: e.toString(), isLoading: false));
}
}
}
4. 性能优化
dart
// 使用Selector/select优化
class OptimizedWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Selector<MyStore, String>(
selector: (context, store) => store.name,
builder: (context, name, child) {
// 只有当name变化时重建
return Text(name);
},
);
}
}
总结
状态管理是Flutter应用架构的核心,选择合适的方案至关重要。建议:
- 从Provider开始,理解基础概念
- 根据项目需求选择,不要过度设计
- 保持一致的模式,整个项目使用统一的状态管理方案
- 考虑团队熟悉度,选择团队熟悉的方案
- 关注性能,特别是大型应用
记住:没有最好的状态管理方案,只有最适合你项目需求的方案。