【问题标题】:Flutter - ProxyProvider how to fix error "Null check operator used on a null value"Flutter - ProxyProvider 如何修复错误“在空值上使用空检查运算符”
【发布时间】:2021-07-15 11:30:26
【问题描述】:

应用的用例:

  • 在应用启动时,它将从 RestAPI 中获取随机用户,
  • 然后它将使用第一次调用的结果进行另一个 RestAPI 调用,这就是我需要 ProxyProvider 的原因。

ma​​in.dart:

return MultiProvider(
    providers: [
      ChangeNotifierProvider(
        create: (_) => RandomUser(),
      ),
      ChangeNotifierProxyProvider<RandomUser, FavoriteList>(
        create: (BuildContext ctx) => FavoriteList(ctx.read<RandomUser>()),
        update: (_, RandomUser user, __) => FavoriteList(user),
      ),

RandomUser 提供者:

class RandomUser extends ChangeNotifier {
  final apiUsers = UsersApi();
  UserModel? _profile;
  String? _userId;

  RandomUser() {
    fetchUser();
  }

  Future<void> fetchUser() async {
    await apiUsers
      .apiGetUser()
      .then((user) => {
        _profile = user,
        _userId = chosenUserId,
      })
      .catchError((e) {
        print("error: $e");
    });

    notifyListeners();
  }

  UserModel get profile => _profile;

  String get chosenUserId => _userId;
}

FavoriteList 提供者:

class FavoriteList extends ChangeNotifier {
  final RandomUser _user;
  final _apiFavoriteList = FavoriteListApi();
  List<FavoriteListModel> _favoriteList = <FavoriteListModel>[];

  FavoriteList(this._user) {
    fetchFavoriteList(_user.chosenUserId);
  }

  Future<void> fetchFavoriteList(String userId) async {
   await _apiFavoriteList
      .apiGetFavoriteList(userId)
      .then((favoriteList) => {
        _favoriteList = favoriteList,
      })
      .catchError((e) {
        print("error: $e");
    });

    notifyListeners();
  }
  
  List<FavoriteListModel> get favoriteList => this._favoriteList;
}

如您所见,FavoriteList provider 需要RandomUser provider 来检索getter 值chosenUserId

当我启动应用程序时,我立即收到错误“Null check operator used on a null value” 在吸气剂chosenUserIdmain.dart 上,我称之为ProxyProvider"create"

我做错了什么? ProxyProvider不应该先初始化第一个Provider,所以我需要的所有值都可用吗?

【问题讨论】:

    标签: flutter dart flutter-provider


    【解决方案1】:

    问题是RandomUser.fetchUser() 在创建FavoriteList 之前尚未完成。您应该编写允许这种情况的代码,例如在RandomUser:

      String? get chosenUserId => _userId;
    

    FavoriteList:

      final? RandomUser _user;
    
      FavoriteList(this._user) {
        if (_user != null && _user?.chosenUserId != null) {
          fetchFavoriteList(_user.chosenUserId);
        }
      }
    
      String? get chosenUserId => _user?.chosenUserId;
    

    fetchUser() 完成后,FavoriteList 将被更新。

    当然,您的 UI 必须处理(临时)丢失的数据。

    顺便说一句,ChangeNotifierProxyProvider 的文档建议您应该像这样构建您的代码:

    ChangeNotifierProxyProvider<MyModel, MyChangeNotifier>(
      create: (_) => MyChangeNotifier(),
      update: (_, myModel, myNotifier) => myNotifier
        ..update(myModel),
      child: ...
    );
    

    在这种情况下,如果要更新 MyModel,那么 MyChangeNotifier 将能够相应地更新。请注意 MyChangeNotifier 如何不再在其构造函数中接收 MyModel。它现在改为通过自定义设置器/方法传递。

    【讨论】:

    • 首先感谢您的回答!我尝试实现这一点,并且您在 FavoriteList 的构造函数中进行的检查,以检查 _user 是否不为空,给了我这个警告:操作数不能为空,因此条件始终为真。去掉条件,这是为什么呢?
    • 仅供参考我还必须更新我的初始帖子,因为 selectedUserId 的 getter 方法写错了,我使用的代码是:String get selectedUserId => _userId;
    • 对不起,我没有注意 null 安全 - 警告是说 _user 不能为 null,所以检查是多余的。我更新了答案以允许 _userchosenUserId 为空。这些更改现在应该生效了。
    • 非常感谢,我越来越近了,现在错误消失了,还有一点,当你启动应用程序时,会第一次调用“fetchFavoriteList(_user.chosenUserId );"它将在用户 ID 参数为空的情况下触发,然后在几秒钟后它会在正确设置参数的情况下重新触发。我不明白为什么当我们放置一个 if(_user != null) 时,它第一次被触发时,Param 为 Null,这意味着如果它输入 If,这意味着 _user 对象可用,对吗?
    • 并且仅供参考 => fetchFavoriteList(_user.chosenUserId);,我必须添加一个“?”在 _user 之后,否则会抛出:参数类型“字符串?”不能分配给参数类型'String'
    【解决方案2】:

    试试这个解决方案

    我的代码是这样的

    providers: [
            ChangeNotifierProvider(create: (ctx) => Auth()),
            ChangeNotifierProxyProvider<Auth, Products>(
              create: (ctx) => Products(null, null, []),
              update: (ctx, auth, previousProducts) => Products(
                  auth.token! ,
                  auth.userId! ,
                  previousProducts == null ? [] : previousProducts.items),
            ),
            ChangeNotifierProvider(create: (ctx) => Cart()),
            ChangeNotifierProxyProvider<Auth, Orders>(
              create: (ctx) => Orders(null, null, []),
              update: (ctx, auth, previousOrders) {
                print(auth);
                return Orders(auth.token!, auth.userId!,
                    previousOrders == null ? [] : previousOrders.orders);
              },
            ),
          ],
    

    并通过将! 更改为?? 来解决此问题

    ChangeNotifierProxyProvider<Auth, Products>(
              create: (ctx) => Products(null, null, []),
              update: (ctx, auth, previousProducts) => Products(
                  auth.token ?? null,
                  auth.userId ?? null,
                  previousProducts == null ? [] : previousProducts.items),
            ),
    

    【讨论】:

      猜你喜欢
      • 2021-08-23
      • 2021-11-10
      • 2022-07-14
      • 1970-01-01
      • 2022-07-04
      • 1970-01-01
      • 2021-08-04
      • 2022-01-05
      • 2021-07-11
      相关资源
      最近更新 更多