未处理的异常:类型 'Null' 不是类型 'String' 的子类型

Unhandled Exception: type 'Null' is not a subtype of type 'String'

我正在学习 Flutter 课程(课程是在 flutter 2 之前录制的)当我 运行 遇到这个错误时:

I/flutter ( 3538): type 'Null' is not a subtype of type 'String'
E/flutter ( 3538): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: type 'Null' is not a subtype of type 'String'
E/flutter ( 3538): #0      Products.fetchAndSetProducts
package:shop_app/providers/products_provider.dart:80
E/flutter ( 3538): <asynchronous suspension>

我试着检查突出显示的行是否有问题,对我来说没问题。

代码如下:

Future<void> fetchAndSetProducts() async {
    var url = Uri.parse(
        'https://flutter-39ecc-default-rtdb.firebaseio.com/products.json');
    try {
      final response = await http.get(url);
      final extractedData = json.decode(response.body) as Map<String, dynamic>;
      final List<Product> loadedProducts = [];
      extractedData.forEach((key, value) {
        loadedProducts.add(Product(
            id: key,
            title: value['title'],
            description: value['description'],
            price: value['price'],
            isFavorite: value['isFavorite'],
            imageUrl: value['imageUrl']));
      });
      _items = loadedProducts;
      notifyListeners();
      // print(json.decode(response.body));
    } catch (error) {
      print(error);
      throw error;  // line 80
    }
  }

我就是这样调用这个函数的

  var _isInit = true;
  var _isLoading = false;
  @override
  void didChangeDependencies() {
    if (_isInit) {
      setState(() {
        _isLoading = true;
      });
      Provider.of<Products>(context).fetchAndSetProducts().then((_) {
        setState(() {
          _isLoading = false;
        });
      });
    }
    _isInit = false;
    super.didChangeDependencies();
  }

请检查您的 Product class。它的属性应该可以是Null.

所以可能是 String? 而不是 String

  Product(
        id: key,
        title: value['title'],
        description: value['description'],
        price: value['price'],
        isFavorite: value['isFavorite'],
        imageUrl: value['imageUrl']));
  }

我查看了 https://flutter-39ecc-default-rtdb.firebaseio.com/products.json 的回复。构造 Product 对象时需要使用一些缺少的键。

发生这种情况是因为您尝试分配的值之一为空,而变量不可为空

        loadedProducts.add(Product(
            id: key,
            title: value['title'],
            description: value['description'],
            price: value['price'],
            isFavorite: value['isFavorite'],
            imageUrl: value['imageUrl']));
      });

看看这段代码,如果你想制作一个产品模型class,如果你让每个变量都可以为空就好了。

class ProductModel {
  int? id;
  String? title;
  String? description;
  double? price;
  bool? isFavorite;
  String? imageUrl;
}

如果你真的很小心地处理来自后端的分配,那就太好了。因为一些后端不一致。

factory ProductModel ProductModel.fromJson(Map<String, dynamic> json) => ProductModel({
  id: json['id'] != null ? (json['id'] as num?)?.toInt() : null, 
//it would be great if you also check if the json['id'] is instance of String or not, because sometimes you can get id with type String from backend
// why use num? instead of int?, because sometimes we can also get double from backend right? and int and double indicator isn't consistent
// that's why num? then cast to the type you want is the best practice
  title: json['title'] as String?,
  
  
  //etc..
});