【问题标题】:Unhandled Exception: type 'Null' is not a subtype of type 'String'未处理的异常:“Null”类型不是“String”类型的子类型
【发布时间】:2021-12-28 23:34:47
【问题描述】:

当我遇到这个错误时,我正在学习 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();
  }

【问题讨论】:

    标签: flutter dart mobile


    【解决方案1】:

    这是因为您尝试分配的值之一为 null 而变量不可为空

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

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

    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..
    });
    

    【讨论】:

      【解决方案2】:

      请检查您的Product 课程。它的属性应该可以是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 对象时,缺少一些需要使用的键。

      【讨论】:

        猜你喜欢
        • 2022-06-30
        • 1970-01-01
        • 2023-02-03
        • 2023-01-27
        • 2021-09-19
        • 2021-07-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多