刚刚了解 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 请求失败的正确方法是什么?
您需要将 AsyncNotifier 方法分为三类:
build)build必须始终返回 的第一个值state,该值从构建结果(错误、数据或未来)映射到 AsyncValue。除了框架之外,永远不build应该调用。
外部变异器必须始终是voidorFuture<void>和 update state,通常通过首先将其设置为AsyncLoading()然后使用AsyncValue.guard来安全地执行函数。
内部助手永远不应该从外部调用,也不应该直接更新state。相反,它们应该将它们的值返回给调用者,这也应该是内部的。(他们也可能会抛出。)因此,这些通常被设为库私有,并标记为@protected。
在您的具体示例中,您login应该 return Future<void>,并调用内部_login函数来完成繁重的工作,该函数返回新User对象或抛出异常。您的构建还可以_login使用字段的初始值进行调用,并且因为它位于内部build,所以未来和异常将得到正确处理。
希望这可以帮助!(我应该就此发表一篇文章......)
| 归档时间: |
|
| 查看次数: |
519 次 |
| 最近记录: |