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

Time:11-18

i was taking a Flutter course (the course was recorded before flutter 2) when i ran into this error:

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>

I tried to check if there was something wrong on the line highlighted and for me it was ok.

Here is the code:

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
    }
  }

This is how i´m calling this function

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

CodePudding user response:

Please check your Product class. Its attributes should be able to be Null.

So it's may be String? not String

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

I checked the response from https://flutter-39ecc-default-rtdb.firebaseio.com/products.json. There are some missing keys that need to use when construct the Product object.

CodePudding user response:

this is happenned because one of the value you're trying to assign is null while the variable is not nullable

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

look at this code, if you want to make a model class of product, it would be great if you make every variable nullable.

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

And it would be great if you really careful with the assignment from the backend. Because some backend aren't consistent.

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