flutter riverpod AsyncNotifier 和 Notifier

Flutter Riverpod:AsyncNotifier 与 Notifier 详细分析对比

一、核心概述

1. Notifier

  • 用途:同步状态管理

  • 适用场景:简单状态,不需要异步操作

  • 状态类型T(任意同步类型)

2. AsyncNotifier

  • 用途:异步状态管理

  • 适用场景:需要异步加载、保存数据(如API调用、数据库操作)

  • 状态类型AsyncValue<T>(包装异步状态)

二、详细对比分析

类定义对比

dart

复制代码
// Notifier - 同步
class CounterNotifier extends Notifier<int> {
  @override
  int build() {
    return 0; // 直接返回同步值
  }
}

// AsyncNotifier - 异步
class UserProfileNotifier extends AsyncNotifier<UserProfile> {
  @override
  FutureOr<UserProfile> build() async {
    // 可以执行异步操作
    return await _fetchUserProfile();
  }
}

状态类型对比

特性 Notifier AsyncNotifier
状态类型 T AsyncValue<T>
初始状态 直接值 AsyncLoading
错误处理 需手动处理 内置错误状态
加载状态 需手动管理 自动管理

AsyncValue 状态类型

dart

复制代码
AsyncValue<T> 有三种状态:
1. AsyncLoading - 加载中
2. AsyncData(T data) - 数据加载成功
3. AsyncError(Object error, StackTrace stackTrace) - 加载失败

三、使用场景详解

适合使用 Notifier 的场景

dart

复制代码
// 1. 计数器
class CounterNotifier extends Notifier<int> {
  @override
  int build() => 0;
  
  void increment() => state++;
  void decrement() => state--;
}

// 2. 简单的表单状态
class FormNotifier extends Notifier<FormData> {
  @override
  FormData build() => FormData.empty();
  
  void updateField(String field, String value) {
    state = state.copyWith(field: value);
  }
}

适合使用 AsyncNotifier 的场景

dart

复制代码
// 1. API数据获取
class ProductsNotifier extends AsyncNotifier<List<Product>> {
  @override
  Future<List<Product>> build() async {
    return await _fetchProducts();
  }
  
  Future<void> refresh() async {
    state = const AsyncValue.loading();
    state = await AsyncValue.guard(() => _fetchProducts());
  }
  
  Future<void> addProduct(Product product) async {
    final newProduct = await _api.addProduct(product);
    state = AsyncValue.data([...state.value!, newProduct]);
  }
}

// 2. 用户认证
class AuthNotifier extends AsyncNotifier<User?> {
  @override
  Future<User?> build() async {
    return await _checkSavedToken();
  }
  
  Future<void> login(String email, String password) async {
    state = const AsyncValue.loading();
    state = await AsyncValue.guard(() => _performLogin(email, password));
  }
}

四、方法对比

Notifier 核心方法

dart

复制代码
abstract class Notifier<T> {
  T build();  // 必须实现,返回初始状态
  T get state; // 当前状态
  set state(T value); // 设置新状态
  void update((T state) => T cb); // 基于当前状态更新
}

AsyncNotifier 核心方法

dart

复制代码
abstract class AsyncNotifier<T> {
  FutureOr<T> build(); // 可以返回 Future
  AsyncValue<T> get state;
  set state(AsyncValue<T> value);
  
  // 特有方法
  Future<void> update((T? state) => FutureOr<T> cb);
  Future<T> future; // 获取 build 返回的 Future
}

五、UI 中使用对比

Notifier 在 UI 中的使用

dart

复制代码
final counterProvider = NotifierProvider<CounterNotifier, int>(
  CounterNotifier.new,
);

Consumer(
  builder: (context, ref, child) {
    final count = ref.watch(counterProvider);
    return Text('Count: $count');
  },
)

AsyncNotifier 在 UI 中的使用

dart

复制代码
final productsProvider = AsyncNotifierProvider<ProductsNotifier, List<Product>>(
  ProductsNotifier.new,
);

Consumer(
  builder: (context, ref, child) {
    final productsAsync = ref.watch(productsProvider);
    
    return productsAsync.when(
      loading: () => CircularProgressIndicator(),
      error: (error, stack) => ErrorWidget(error),
      data: (products) => ListView.builder(
        itemCount: products.length,
        itemBuilder: (context, index) => ProductItem(products[index]),
      ),
    );
  },
)

六、错误处理对比

Notifier 错误处理(需手动)

dart

复制代码
class ManualErrorNotifier extends Notifier<Result<int>> {
  @override
  Result<int> build() => Result.success(0);
  
  void riskyOperation() {
    try {
      final result = _doSomethingRisky();
      state = Result.success(result);
    } catch (e) {
      state = Result.failure(e);
    }
  }
}

AsyncNotifier 错误处理(自动)

dart

复制代码
class AutoErrorNotifier extends AsyncNotifier<int> {
  @override
  Future<int> build() async {
    // 自动捕获异常并转为 AsyncError
    return await _fetchData();
  }
  
  Future<void> retry() async {
    // AsyncValue.guard 自动处理错误
    state = await AsyncValue.guard(() => _fetchData());
  }
}

七、性能与最佳实践

性能考虑

  1. Notifier:更轻量,适合频繁更新的状态

  2. AsyncNotifier:稍重,但提供了完整的异步状态管理

最佳实践

何时选择 Notifier
  • 状态同步且简单

  • 不需要加载/错误状态

  • 状态更新频繁

  • 本地状态管理

何时选择 AsyncNotifier
  • 需要异步初始化

  • 需要处理加载状态

  • 需要内置错误处理

  • 与API/数据库交互

  • 复杂的数据流管理

混合使用示例

dart

复制代码
// 使用 AsyncNotifier 处理数据获取,Notifier 处理 UI 状态
final userProvider = AsyncNotifierProvider<UserNotifier, User>(
  UserNotifier.new,
);

final themeProvider = NotifierProvider<ThemeNotifier, ThemeData>(
  ThemeNotifier.new,
);

// 在业务逻辑中结合使用
class UserDashboardNotifier extends Notifier<DashboardState> {
  @override
  DashboardState build() {
    // 监听异步用户数据
    final userAsync = ref.watch(userProvider);
    final theme = ref.watch(themeProvider);
    
    return userAsync.when(
      loading: () => DashboardState.loading(theme),
      error: (e, _) => DashboardState.error(e, theme),
      data: (user) => DashboardState.success(user, theme),
    );
  }
}

八、迁移示例

从 Notifier 迁移到 AsyncNotifier

dart

复制代码
// 之前:手动管理加载状态
class OldUserNotifier extends Notifier<UserState> {
  @override
  UserState build() => UserState.loading();
  
  Future<void> loadUser() async {
    state = UserState.loading();
    try {
      final user = await api.getUser();
      state = UserState.success(user);
    } catch (e) {
      state = UserState.error(e);
    }
  }
}

// 之后:使用 AsyncNotifier
class NewUserNotifier extends AsyncNotifier<User> {
  @override
  Future<User> build() => api.getUser();
  
  Future<void> refresh() async {
    state = const AsyncValue.loading();
    state = await AsyncValue.guard(() => api.getUser());
  }
}

总结

维度 Notifier AsyncNotifier
复杂度 简单 中等
异步支持 需手动处理 内置支持
状态管理 同步状态 异步状态包装
错误处理 手动 自动
加载状态 手动 自动
适用场景 简单同步状态 异步数据流
性能 更轻量 稍重但功能全

选择建议

  • 如果状态完全是同步的,不需要加载/错误状态 → 使用 Notifier

  • 如果涉及异步操作(API、数据库等) → 使用 AsyncNotifier

  • 对于复杂应用,通常需要混合使用两者

相关推荐
lili-felicity11 分钟前
基础入门 Flutter for OpenHarmony:三方库实战 flutter_phone_direct_caller 电话拨号详解
flutter
不爱吃糖的程序媛32 分钟前
Flutter-OH 插件适配 HarmonyOS 实战:以屏幕方向控制为例
flutter·华为·harmonyos
松叶似针35 分钟前
Flutter三方库适配OpenHarmony【doc_text】— 文件格式路由:.doc 与 .docx 的分流策略
flutter·harmonyos
阿林来了43 分钟前
Flutter三方库适配OpenHarmony【flutter_web_auth】— FlutterPlugin 与 AbilityAware 双接口实现
flutter·harmonyos
LawrenceLan43 分钟前
31.Flutter 零基础入门(三十一):Stack 与 Positioned —— 悬浮、角标与覆盖布局
开发语言·前端·flutter·dart
阿林来了43 分钟前
Flutter三方库适配OpenHarmony【flutter_web_auth】— openLink API 与浏览器启动策略
flutter
lili-felicity1 小时前
基础入门 Flutter for OpenHarmony:第三方库实战 cryptography_flutter 加密解密详解
flutter
lqj_本人1 小时前
Flutter三方库适配OpenHarmony【apple_product_name】构建设备信息展示页面
flutter
阿林来了1 小时前
Flutter三方库适配OpenHarmony【flutter_web_auth】— 深度链接(Deep Link)机制全解析
flutter
松叶似针1 小时前
Flutter三方库适配OpenHarmony【doc_text】— FlutterPlugin 接口实现与 MethodChannel 注册
flutter·harmonyos