公告

👇欢迎大家关注公众号&私信交流👇

Skip to content

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;
});

最佳实践

  1. 使用 StateNotifier 管理复杂状态
  2. 合理使用 autoDispose
  3. 避免在 Provider 中使用全局变量
  4. 使用 family 修饰符传递参数
  5. 合理组织 Provider 代码

注意事项

  1. 避免在 Provider 中直接修改状态
  2. 注意状态更新的性能影响
  3. 合理处理异步操作
  4. 注意内存泄漏
  5. 使用正确的依赖注入方式

总结

Riverpod 提供了一种类型安全、可测试的状态管理方案。通过合理使用 Provider 和 StateNotifier,可以构建出可维护性更好的应用程序。理解并掌握 Riverpod 的使用对于开发高质量的 Flutter 应用至关重要。