Flutter Riverpod 状态管理详解
简介
Riverpod 是 Provider 的重新设计版本,它提供了更安全的依赖管理和更好的代码组织方式。Riverpod 完全支持编译时安全,并且可以轻松处理异步数据。
基本概念
Provider
dart
// 基础 Provider
final nameProvider = Provider<String>((ref) => 'John Doe');
// 状态 Provider
final counterProvider = StateProvider<int>((ref) => 0);
// 异步 Provider
final userProvider = FutureProvider<User>((ref) async {
final repository = ref.read(repositoryProvider);
return repository.fetchUser();
});
StateNotifier
dart
class Counter extends StateNotifier<int> {
Counter() : super(0);
void increment() => state++;
void decrement() => state--;
}
final counterProvider = StateNotifierProvider<Counter, int>((ref) {
return Counter();
});
基本用法
提供状态
dart
void main() {
runApp(
ProviderScope(
child: MyApp(),
),
);
}
使用状态
dart
// 读取状态
Consumer(
builder: (context, ref, child) {
final count = ref.watch(counterProvider);
return Text('Count: $count');
},
);
// 修改状态
ref.read(counterProvider.notifier).increment();
完整示例
dart
// 用户模型
class User {
final String id;
final String name;
final int age;
User({
required this.id,
required this.name,
required this.age,
});
}
// 用户状态
class UserState {
final User? user;
final bool isLoading;
final String? error;
UserState({
this.user,
this.isLoading = false,
this.error,
});
UserState copyWith({
User? user,
bool? isLoading,
String? error,
}) {
return UserState(
user: user ?? this.user,
isLoading: isLoading ?? this.isLoading,
error: error ?? this.error,
);
}
}
// 用户 Notifier
class UserNotifier extends StateNotifier<UserState> {
final UserRepository _repository;
UserNotifier(this._repository) : super(UserState());
Future<void> fetchUser() async {
state = state.copyWith(isLoading: true, error: null);
try {
final user = await _repository.fetchUser();
state = state.copyWith(
user: user,
isLoading: false,
);
} catch (e) {
state = state.copyWith(
error: e.toString(),
isLoading: false,
);
}
}
Future<void> updateUser(String name, int age) async {
state = state.copyWith(isLoading: true, error: null);
try {
final updatedUser = await _repository.updateUser(
state.user!.id,
name,
age,
);
state = state.copyWith(
user: updatedUser,
isLoading: false,
);
} catch (e) {
state = state.copyWith(
error: e.toString(),
isLoading: false,
);
}
}
}
// Provider 定义
final userRepositoryProvider = Provider<UserRepository>((ref) {
return UserRepository();
});
final userProvider = StateNotifierProvider<UserNotifier, UserState>((ref) {
final repository = ref.watch(userRepositoryProvider);
return UserNotifier(repository);
});
// 页面组件
class UserPage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final userState = ref.watch(userProvider);
return Scaffold(
appBar: AppBar(title: Text('Riverpod Demo')),
body: Center(
child: userState.isLoading
? CircularProgressIndicator()
: userState.error != null
? Text('Error: ${userState.error}')
: userState.user == null
? ElevatedButton(
onPressed: () {
ref.read(userProvider.notifier).fetchUser();
},
child: Text('Load User'),
)
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Name: ${userState.user!.name}',
style: TextStyle(fontSize: 24),
),
Text(
'Age: ${userState.user!.age}',
style: TextStyle(fontSize: 24),
),
ElevatedButton(
onPressed: () {
ref.read(userProvider.notifier).updateUser(
'John Doe',
30,
);
},
child: Text('Update User'),
),
],
),
),
);
}
}
高级用法
组合 Provider
dart
final userSettingsProvider = Provider<Settings>((ref) {
final user = ref.watch(userProvider);
return Settings(userId: user.id);
});
自动释放
dart
final cacheProvider = Provider.autoDispose<Cache>((ref) {
final cache = Cache();
ref.onDispose(() => cache.dispose());
return cache;
});
状态保持
dart
final counterProvider = StateProvider.autoDispose<int>((ref) {
ref.maintainState = true;
return 0;
});
最佳实践
- 使用 StateNotifier 管理复杂状态
- 合理使用 autoDispose
- 避免在 Provider 中使用全局变量
- 使用 family 修饰符传递参数
- 合理组织 Provider 代码
注意事项
- 避免在 Provider 中直接修改状态
- 注意状态更新的性能影响
- 合理处理异步操作
- 注意内存泄漏
- 使用正确的依赖注入方式
总结
Riverpod 提供了一种类型安全、可测试的状态管理方案。通过合理使用 Provider 和 StateNotifier,可以构建出可维护性更好的应用程序。理解并掌握 Riverpod 的使用对于开发高质量的 Flutter 应用至关重要。