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

Clá*_*tas 9 mobile dart flutter

当我遇到这个错误时,我正在参加 Flutter 课程(该课程是在 flutter 2 之前录制的):

\n
I/flutter ( 3538): type 'Null' is not a subtype of type 'String'\nE/flutter ( 3538): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: type 'Null' is not a subtype of type 'String'\nE/flutter ( 3538): #0      Products.fetchAndSetProducts\npackage:shop_app/providers/products_provider.dart:80\nE/flutter ( 3538): <asynchronous suspension>\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

这是代码:

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

这就是 i\xc2\xb4m 调用该函数的方式

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

小智 7

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

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

看看这段代码,如果你想创建一个产品的模型类,如果你让每个变量都可以为空,那就太好了。

class ProductModel {
  int? id;
  String? title;
  String? description;
  double? price;
  bool? isFavorite;
  String? imageUrl;
}
Run Code Online (Sandbox Code Playgroud)

如果您真的仔细处理后端的分配,那就太好了。因为有些后端不一致。

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..
});
Run Code Online (Sandbox Code Playgroud)


小智 2

请检查您的Product班级。其属性应该是可以的Null

所以可能String?不是String

  Product(
        id: key,
        title: value['title'],
        description: value['description'],
        price: value['price'],
        isFavorite: value['isFavorite'],
        imageUrl: value['imageUrl']));
  }
Run Code Online (Sandbox Code Playgroud)

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