我只是在学习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");  }
}

我想在用户界面的Switch语句中使用它:

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

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

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

推荐答案

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

  • 基础设施(build)
  • 外部变异体(公共API)
  • 内部帮助者(通常为异步)

build必须始终返回state的第一个值,该值从生成结果(错误、数据或future )映射到AsyncValue.除框架外,应调用buildnever.

外部Mutations 变量必须始终为voidFuture<void>,并更新state,通常首先将其设置为AsyncLoading(),然后使用AsyncValue.guard来安全地执行函数.

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

在您的特定示例中,您的login应该返回Future<void>,并调用内部_login函数来执行繁重的任务,该函数要么返回新的User对象,要么抛出.您的构建还可以使用字段的初始值调用_login,因为它在build之内,所以可以正确地处理期货和异常.

希望这会有帮助!(我应该发表一篇关于这方面的文章……)

Flutter相关问答推荐

当MyChangeNotifier更改时如何计算函数,而无需在构建方法中进行不必要的调用- Flutter

Flutter—如何在Riverpod中使用全类状态?

在Flutter 中创建自定义Snackbar类

将图标呈现在Flutter 克牌小工具的角落上

'Flutter的无效常数值错误

将列表<;Events>;从Flutter 应用程序中的函数传回EventLoader属性时出错

为Android生成时出现Flutter 错误:给定资源值的<;COLOR&>无效

带有附加图像的ListTile

如何将小部件代码移动到另一个文件以获得更好的可读性

在允许屏幕 Select 和点击的同时保持通用对话框显示

Flutter中如何实现带有变化图标的浮动操作按钮?

Flutter Dart 功能弹出错误的小部件?

Flutter/Dart - 从外部类更新状态

为什么将 bloc 提供程序放在单独的文件/类中会引发错误?

如何更改中心的圆形进度指示器

flutter 创建一个带有 2 个图标的按钮

如何在 Flutter 中创建 Facebook 创建帖子屏幕?

从物理设备 Flutter 中移除 USB 后启动画面不可见?

我几乎每次都将 Stateless Widget 与 BLoC 一起使用.我错了吗?

Textfield 和 MasonryGrid 给出错误(垂直视口的高度没有限制)