简体   繁体   中英

"Unhandled Exception: type 'String' is not a subtype of type 'bool' " ==TypeError

i just want to update my favorite status in Firebase when user is click on favorite icon.
all is done: but when i fetch data i got this error:
"Unhandled Exception: type 'String' is not a subtype of type 'bool' "
-isFavorite is a bool so what can i do?

here i got the error in this Function:

  Future<void> fetchAndSetProducts() async {
var url =
    'https://ecommerce-test-753ad-default-rtdb.firebaseio.com/products.json?auth=$authToken';
try {
  final response = await http.get(Uri.parse(url));
  final extractedData = json.decode(response.body) as Map<String, dynamic>;
  if (extractedData == {}) {
    return;
  }
  url =
      'https://ecommerce-test-753ad-default-rtdb.firebaseio.com/userFavorites/$userId.json?auth=$authToken';
  final favoriteResponse = await http.get(Uri.parse(url));
  final favoriteData = json.decode(favoriteResponse.body);
  final List<Product> loadedProduct = [];
  extractedData.forEach((key, value) {
    loadedProduct.add(
      Product(
        id: key,
        title: value['title'],
        price: value['price'],
        imageUrl: value['imageUrl'],
        description: value['description'],
        isFavorite:
            favoriteData == null? false : favoriteData[key] ?? false,
      ),
    );
  });
  _productItems = loadedProduct;
  notifyListeners();
} catch (e) {
  rethrow;
}
}

this is product Model class:

class Product with ChangeNotifier {
 final String id;
 final String title;
 final double price;
 final String imageUrl;
 final String description;
 bool isFavorite;

 Product({
 required this.id,
 required this.title,
 required this.price,
 required this.imageUrl,
 required this.description,
 this.isFavorite = false,
  });


 void _setFavValue(bool newValue) {
  isFavorite = newValue;
  notifyListeners();
  }

Future<void> toggleFavoriteStatus(String authToken, String 
 userId) async {
  final oldStatus = isFavorite;
   isFavorite = !isFavorite;
  notifyListeners();
 final url =
     'https://ecommerce-test-753ad-default- 
rtdb.firebaseio.com/userFavorites/$userId/$id.json? 
auth=$authToken';
  try {
   final response = await http.put(
     Uri.parse(url),
    body: json.encode(isFavorite),
  );
  if (response.statusCode >= 400) {
    _setFavValue(oldStatus);
  }
} catch (error) {
  _setFavValue(oldStatus);
}
}

}

The problem seems to be that the favoriteData[key] value that you get back from Firebase is in the form of a String , not a bool as you want it to be. Add these lines:

  extractedData.forEach((key, value) {

    // Two added lines:
    print('favoriteData[$key] is ${favoriteData[key]}');
    print('favoriteData[$key] is of type ${favoriteData[key].runtimeType}');

    loadedProduct.add(
      Product(
        id: key,
        title: value['title'],
        price: value['price'],
        imageUrl: value['imageUrl'],
        description: value['description'],
        isFavorite:
            favoriteData == null? false : favoriteData[key] ?? false,
      ),
    );

That will tell you exactly what is in that variable. If the output is:

favoriteData[some_key] is true
favoriteData[some_key] is of type String

then you know that you have accidentally uploaded the value in the form of a the String 'true' rather than the bool value true . Maybe you have uploaded '$isFavorite' instead of isFavorite or something...?

If you find that the value contains something else entirely, neither 'true' nor 'false' nor 'null', then you'll think of next steps from there, Hopefully, the print() will give you a clue. in any case.


Edit: Since you seem to be looking for a quick fix, try this instead:

change this:

extractedData.forEach((key, value) {
    loadedProduct.add(
      Product(
        id: key,
        title: value['title'],
        price: value['price'],
        imageUrl: value['imageUrl'],
        description: value['description'],
        isFavorite:
            favoriteData == null? false : favoriteData[key] ?? false,
      ),
    );
  });

to this:

extractedData.forEach((key, value) {
    bool _isFavorite = favoriteData[key] != null && favoriteData[key] == 'true' ? true: false;
    loadedProduct.add(
      Product(
        id: key,
        title: value['title'],
        price: value['price'],
        imageUrl: value['imageUrl'],
        description: value['description'],
        isFavorite: _isFavorite,
      ),
    );
  });

At least that's MORE likely to work than that other answer... if you REALLY can't tell us what's really inside that favoriteData[key] value of yours!

As you mentioned the value inside favoriteData is {-NAQTpO0QX4BEzkQaVdM: isFavorite} so when you call favoriteData[key] it return a string which is 'isFavorite' but you need a bool value for your Product object then we need convert a string value to bool value with this approach below.

change this:

extractedData.forEach((key, value) {
    loadedProduct.add(
      Product(
        id: key,
        title: value['title'],
        price: value['price'],
        imageUrl: value['imageUrl'],
        description: value['description'],
        isFavorite:
            favoriteData == null? false : favoriteData[key] ?? false,
      ),
    );
  });

to this:

extractedData.forEach((key, value) {
    var _isFavorite = favoriteData[key] != null && favoriteData[key] == 'isFavorite' ? true: false;
    loadedProduct.add(
      Product(
        id: key,
        title: value['title'],
        price: value['price'],
        imageUrl: value['imageUrl'],
        description: value['description'],
        isFavorite:
            favoriteData == null? false : _isFavorite,
      ),
    );
  });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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