Flutter第三方常用组件包学习之状态管理

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. 选择建议

  1. 新手/小型项目 :推荐 Provider,学习成本低,官方推荐
  2. 需要快速开发 :推荐 GetX,功能全面,开发效率高
  3. 大型/复杂项目 :推荐 RiverpodBLoC,类型安全,可维护性好
  4. 需要强响应式 :推荐 MobX,响应式编程体验好
  5. 企业级应用 :推荐 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应用架构的核心,选择合适的方案至关重要。建议:

  1. 从Provider开始,理解基础概念
  2. 根据项目需求选择,不要过度设计
  3. 保持一致的模式,整个项目使用统一的状态管理方案
  4. 考虑团队熟悉度,选择团队熟悉的方案
  5. 关注性能,特别是大型应用

记住:没有最好的状态管理方案,只有最适合你项目需求的方案。

相关推荐
Yiyi_Coding2 小时前
Proxy详解
java·前端·javascript
Engineer邓祥浩2 小时前
JVM学习笔记(5) 第二部分 自动内存管理 第4章 虚拟机性能监控、故障处理工具
jvm·笔记·学习
追光的蜗牛丿2 小时前
C++传递参数时什么情况下传递引用
开发语言·javascript·c++
九狼JIULANG2 小时前
【无标题】
android·flutter·开源·github
摸鱼仙人~2 小时前
前端开发中“共享预览链接”场景-企业级最简方案:Vue + 极简后端(2 接口 1 张表)
前端·javascript·vue.js
woai33642 小时前
JVM学习-基础篇-垃圾回收
java·jvm·学习
不爱吃糖的程序媛2 小时前
Flutter应用运行到鸿蒙PC指南
flutter·华为·harmonyos
不爱吃糖的程序媛2 小时前
Flutter OH Engine 构建指导(macOS 版本)
flutter·华为·harmonyos
深蓝海拓2 小时前
S7-1500学习笔记:Array数据类型
笔记·学习·plc