Riverpod 2.0 - 如何使用 FutureOr 和 AutoDisposeAsyncNotifier 处理 api 状态代码?

J. *_*yan 2 flutter riverpod

刚刚了解 Riverpod,我不确定如何处理 API 请求的状态代码。我还没有找到任何很好的例子来优雅地处理这个问题。我正在研究一个简化的登录测试来解决这个问题:

final LoginAsyncProvider = AsyncNotifierProvider.autoDispose<LoginProvider, User>(() {
  return LoginProvider();
});

class LoginProvider extends AutoDisposeAsyncNotifier<User> {

  FutureOr<User> login({required String userName, required String password}) async {
    final response = await http.post(Uri.https(Api.mainDomain, Api.login));
    final json = jsonDecode(response.body) as Map<String, dynamic>;
    User _user = User.fromJson(json);
    state = AsyncData(_user);
    return _user;
  }

  @override
  FutureOr<User> build() async {
    return login(userName: "someUser", password: "somePass");  }
}
Run Code Online (Sandbox Code Playgroud)

我想在 UI 中的 switch 语句中使用它:

...
    child: switch (userAsyncValue) { 
      AsyncData(:final value) => Text(text: userAsyncValue.userName),
      AsyncError() => const Text('Some Error happened'),
      _ => const CircularProgressIndicator(),
    },
...

Run Code Online (Sandbox Code Playgroud)

final json = jsonDecode(response.body) as Map<String, dynamic>;显然,当response.statusCode!=200and 不返回 中的数据时,这在语句上失败response.body

处理 API 请求失败的正确方法是什么?

Ran*_*rtz 8

您需要将 AsyncNotifier 方法分为三类:

  • 基础设施 (build
  • 外部修改器(公共 API)
  • 内部助手(通常是异步的)

build必须始终返回 的第一个值state,该值从构建结果(错误、数据或未来)映射到 AsyncValue。除了框架之外,永远不build应该调用。

外部变异器必须始终是voidorFuture<void>和 update state,通常通过首先将其设置为AsyncLoading()然后使用AsyncValue.guard来安全地执行函数。

内部助手永远不应该从外部调用,也不应该直接更新state。相反,它们应该将它们的值返回给调用者,这也应该是内部的。(他们也可能会抛出。)因此,这些通常被设为库私有,并标记为@protected

在您的具体示例中,您login应该 return Future<void>,并调用内部_login函数来完成繁重的工作,该函数返回新User对象或抛出异常。您的构建还可以_login使用字段的初始值进行调用,并且因为它位于内部build,所以未来和异常将得到正确处理。

希望这可以帮助!(我应该就此发表一篇文章......)