简体   繁体   English

列表中的状态未更新,Flutter Provider

[英]State not updating in a List, Flutter Provider

When I try to update a list, I have 2 issues, one method (Method 1 below) only updates the data I'm passing and the rest of the data is null and I have the error Null check operator used on a null value , so my widget breaks when I listen to changes.当我尝试更新列表时,我有 2 个问题,一种方法(下面的方法 1)仅更新我传递的数据,其余数据为null ,并且我Null check operator used on a null value ,所以当我听更改时,我的小部件会中断。 The other method (Method 2 below) has issues because I can not specify where in the list should I update the data and I get an error Illegal assignment to non-assignable expression. Missing selector such as '.identifier' or '[0]'. Try adding a selector.另一种方法(下面的方法 2)存在问题,因为我无法指定应该在列表中的哪个位置更新数据,并且出现错误Illegal assignment to non-assignable expression. Missing selector such as '.identifier' or '[0]'. Try adding a selector. Illegal assignment to non-assignable expression. Missing selector such as '.identifier' or '[0]'. Try adding a selector. So I'm not sure what do now, what am I missing.所以我不确定现在做什么,我错过了什么。 The code:编码:

Method 1:方法一:

List<ItemData>? _items = [];

List<ItemData>? get items => _items;

//Updates only the price and the other data in the state goes null
updatePrice(ItemData price) {
    _items![_items!.indexWhere((element) => element.itemId == price.itemId)] = price;
    notifyListeners();
  }

Method 2:方法二:

List<ItemData>? _items = [];

List<ItemData>? get items => _items;

updatePrice(ItemData price) {
// I can't use this since I have to add an selector and I don't understand how
    _items!.firstWhere((element) => element.itemId == price.itemId) = price;
    notifyListeners();
  }

The API call: API 调用:

 Future<ItemData> patchFee(
      currency, fee, itemId, transactionId) async {
    final response = await (ApiRequest(Method.PATCH, '/items',
        body: jsonEncode({
          "itemId": itemId,
          "transactionId": transactionId,
          "fees": [
            {
              "currency": currency,
              "type": "EXPENSE",
              "fee": fee,
              "description": "Item price",
            }
          ],
        })));
    Map<String, dynamic> jsonDecodedResponse =
        jsonDecode(utf8.decode(response!.bodyBytes));
    var list = jsonDecodedResponse['data']['fees'] as List;
    List<Fees> feesList = list.map((i) => Fees.fromJson(i)).toList();
    return ItemData(
      itemId: jsonDecodedResponse['data']['itemId'],
      transactionId: jsonDecodedResponse['data']['transactionId'],
      fees: feesList,
    );
  }

Action for the API call: API 调用的操作:

final itemStore = Provider.of<ItemStore>(context, listen: true);

...

TextButton(
            style: TextButton.styleFrom(
              textStyle: const TextStyle(fontSize: 20),
            ),
            onPressed: () async {
       final response = await patchFee(
      USD, 300, 123, 333);

      itemStore.updatePrice(response);
},
            child: const Text('Update Price'),
          ),

The patch goes through with status 200, I listen to the changes with final itemStore = Provider.of<ItemStore>(context, listen: true);补丁以状态 200 结束,我使用 final itemStore = Provider.of<ItemStore>(context, listen: true);更改, so I assume the error is that I'm updating the state with my updatePrice(price) method wrong, but can't seem to figure it out what and why. ,所以我认为错误是我用我的updatePrice(price)方法错误地更新了状态,但似乎无法弄清楚是什么以及为什么。 Thanks you in advance for the help.提前感谢您的帮助。

If you're not sure about what you're doing, try to keep your code as simple as possible.如果您不确定自己在做什么,请尽量让您的代码保持简单。

Playing with the indexWhere , firstWhere ... methods can be tricky if you don't know what you're doing, even more with the null-safety.如果您不知道自己在做什么,使用indexWherefirstWhere ... 方法可能会很棘手,尤其是使用 null 安全性。

If you wanna update a single item in your list, you could consider using a simple for loop like this :如果您想更新列表中的单个项目,可以考虑使用这样的简单for loop

void updatePrice(ItemData price) {
  //Making a shallow copy of the original list
  var datasUpdate = _items?.toList();
  
  //Since the datasUpdate is a local var
  //we can null-check it to avoid using "!" everywhere
  if (datasUpdate != null) {
    for (int i = 0; i < datasUpdate.length; i++) {
      if (datasUpdate[i].id == price.id) {
        datasUpdate[i] = price;
        break;
      }
    }
    
    //Finally we update your initial List.
    //No need to use a shallow copy here
    _items = datasUpdate;
    notifyListeners();
  }
}

A fully working example is available here on this dartpad此 dartpad 上提供了一个完整的工作示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM