flutter show late initialization error which flutter provider package? - flutter

why this error is shown on emulator ? it show in _items when debugging.
in flutter provider show error on emulator Late Initialization error : field _ items has not been initialize. it show testing/ error
class CartItem {
final String id;
final String title;
final int quantity;
final double price;
CartItem({
required this.id,
required this.title,
required this.quantity,
required this.price,
});
}
class Cart with ChangeNotifier {
late Map<String, CartItem> _items;
Map<String, CartItem> get items {
return {..._items};
}
int get iteamCount {
return _items.length;
}
void addItem(String productId, double price, String title) {
if (_items.containsKey(productId)) {
//change quantity
_items.update(
productId,
(existingCartItem) => CartItem(
id: existingCartItem.id,
title: existingCartItem.title,
quantity: existingCartItem.quantity + 1,
price: existingCartItem.price,
));
} else {
_items.putIfAbsent(
productId,
() => CartItem(
id: DateTime.now().toString(),
title: title,
price: price,
quantity: 1,
));
}
}
}

_items should be initialized before used.
Or you can just replace late Map<String, CartItem> _items with Map<String, CartItem> _items = {}.

Related

Firebase Map type returns null in flutter

In Firebase, I have a field called stockBySize, as a map
stockBySize
M: "5"
L: "2"
In flutter app, thats my model:
class Product {
String? id;
String? category;
String? name;
String? description;
String? color;
String? price;
List<String>? images;
Map<String, String>? stockBySize;
factory Product.fromFirestore(
DocumentSnapshot<Map<String, dynamic>> snapshot,
SnapshotOptions? options,
) {
final data = snapshot.data();
return Product(
id: data?['id'],
category: data?['category'],
name: data?['name'],
description: data?['description'],
color: data?['color'],
price: data?['price'],
images: data?['images'] is Iterable ? List.from(data?['images']) : null,
stockBySize: data?['stockBySize'] is Iterable
? Map<String, String>.from(data?['stockBySize'])
: null,
);
}
Below is the code where I read the Firebase data:
Future<List<Product>> findProducts() async {
final query = db.collection("products").withConverter(
fromFirestore: Product.fromFirestore,
toFirestore: (Product product, _) => product.toFirestore(),
);
try {
final docSnap = await query.get();
List<Product> products = [];
docSnap.docs.forEach((element) {
products.add(
Product(
id: element.id,
category: element.data().category,
name: element.data().name,
description: element.data().description,
color: element.data().color,
price: element.data().price,
images: element.data().images,
stockBySize: element.data().stockBySize,
),
);
});
log(products.toString());
return products;
} on FirebaseException {
rethrow;
}
}
The problem: the field stockBySize is always null.
Whats wrong???? The field is written correctly and there is data in firebase
Try the following code:
class Product {
Product({
required this.id,
required this.category,
required this.name,
required this.description,
required this.color,
required this.price,
required this.images,
required this.stockBySize,
});
String? id;
String? category;
String? name;
String? description;
String? color;
String? price;
List<String>? images;
Map<String, dynamic>? stockBySize;
factory Product.fromFirestore(
DocumentSnapshot<Map<String, dynamic>> snapshot,
SnapshotOptions? options,
) {
final data = snapshot.data();
return Product(
id: data?['id'],
category: data?['category'],
name: data?['name'],
description: data?['description'],
color: data?['color'],
price: data?['price'],
images: data?['images'] is Iterable ? List.from(data?['images']) : null,
stockBySize: data?['stockBySize'] is Map<String, dynamic> ? Map<String, dynamic>.from(data?['stockBySize']) : null,
);
}
}

type 'Null' is not a subtype of type 'String' in the flutter app development

I'm developing an app that manages glossary food items. I can't figure out what is the mistake I've done. Here's my code...
First, I've created a class called 'Product' that contains all the required fields like Product name, Product Image, item Type and quantity etc
The model :
class Product {
String id;
final String productName;
final String itemType;
final String productImage;
final String purchasedDate;
final String expiryDate;
final String quantity;
Product({
this.id = '',
required this.productName,
required this.productImage,
required this.itemType,
required this.purchasedDate,
required this.expiryDate,
required this.quantity,
});
Map<String, dynamic> toJson() => {
'id': id,
'ProductImage': productImage,
'ProductName': productName,
'PurchasedDate': purchasedDate,
'ExpiryDate': expiryDate,
'ItemType': itemType,
'Quantity': quantity,
};
static Product fromJson(Map<String, dynamic> json) => Product(
productName: json['ProductName'],
productImage: json['productImage'],
itemType: json['ItemType'],
purchasedDate: json['purchasedDate'],
expiryDate: json['ExpiryDate'],
quantity: json['Quantity']);
}
The code for implementation :
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:expire_x/utils/product.dart';
import 'package:flutter/material.dart';
class HomePageTwo extends StatefulWidget {
const HomePageTwo({Key? key}) : super(key: key);
#override
State<HomePageTwo> createState() => _HomePageTwoState();
}
class _HomePageTwoState extends State<HomePageTwo> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("home page"),
),
body: StreamBuilder<List<Product>>(
stream: readProduct(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text("Something went wrong> ${snapshot.error}");
} else if (snapshot.hasData) {
final product = snapshot.data!;
return ListView(
children: product.map(buildProduct).toList(),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
Widget buildProduct(Product product) => ListTile(
title: Text(product.productName),
);
Stream<List<Product>> readProduct() => FirebaseFirestore.instance
.collection('Products')
.snapshots()
.map((snapshot) =>
snapshot.docs.map((doc) => Product.fromJson(doc.data())).toList());
Future CreateProduct() async {
final docProduct = FirebaseFirestore.instance.collection('Products').doc();
final product = Product(
id: docProduct.id,
productImage: 'ddd',
productName: "productName",
purchasedDate: "purchasedDate",
expiryDate: "expiryDate",
itemType: "itemType",
quantity: "quantity",
);
final json = product.toJson();
await docProduct.set(json);
}
}
The json response from firebase that I wanted :
json response
And the error :
type 'Null' is not a subtype of type 'String'
In the emulator
I'm new to flutter. Can anyone please help me?
This error occurs when you add required keyword in the constructor. And one of the value appears to be null.
To overcome this
Make sure that all the fields in all the documents is filled.
OR
Avoid using required use null operator instead ? if you are not sure the documents to be filled everytime.
Like:
class Product {
String? id;
String? productName;
String? itemType;
String? productImage;
String? purchasedDate;
String? expiryDate;
String? quantity;
Product({
this.id = '',
this.productName,
this.productImage,
this.itemType,
this.purchasedDate,
this.expiryDate,
this.quantity,
});
Typo mistake in your model class
static Product fromJson(Map<String, dynamic> json) => Product(
productName: json['ProductName'],
productImage: json['ProductImage'], // It should be 'ProductImage'
itemType: json['ItemType'],
purchasedDate: json['PurchasedDate'], // and this should be 'PurchasedDate'
expiryDate: json['ExpiryDate'],
quantity: json['Quantity']);

I m very much confused seeing a statement of Map in flutter project

I am following a tutor channel..almost going we'll but confused at a statement
there is a provider class named cart.. and as we know,,, cart contains more than one cart items...but in code...tutor has given Map<String,CartItem> items={} and I think he should take List<Map<String,CartItem>> items=[];
here is a code
import 'package:flutter/foundation.dart';
class CartItem {
final String id;
final String title;
final int quantity;
final double price;
CartItem({
#required this.id,
#required this.title,
#required this.quantity,
#required this.price,
});
}
class Cart with ChangeNotifier {
Map<String, CartItem> _items = {};
Map<String, CartItem> get items {
return {..._items};
}
int get itemCount {
return _items.length;
}
void addItem(
String productId,
double price,
String title,
) {
if (_items.containsKey(productId)) {
// change quantity...
_items.update(
productId,
(existingCartItem) => CartItem(
id: existingCartItem.id,
title: existingCartItem.title,
price: existingCartItem.price,
quantity: existingCartItem.quantity + 1,
),
);
} else {
_items.putIfAbsent(
productId,
() => CartItem(
id: DateTime.now().toString(),
title: title,
price: price,
quantity: 1,
),
);
}
notifyListeners();
}
}

"Non-nullable instance field '_items' must be initialized.\nTry adding an initializer it

I am trying to make a modal for shopping cart but this gives me an error.
my dart sdk version:2.12.0>3.0.0
I tried using 'late' before this map but it giving me error in output result that lateinitialization error: field '_items' has not be initialized
Map<String, CartItem> _items;
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
class CartItem with ChangeNotifier {
final String id;
final String title;
final int quantity;
final double price;
CartItem(
{required this.id,
required this.title,
required this.price,
required this.quantity});
}
class Cart with ChangeNotifier {
Map<String, CartItem> _items; //error _items
Map<String, CartItem> get items {
return {..._items};
}
int get itemcount {
return _items.length;
}
void addItems(String productId, double price, String title) {
if (_items.containsKey(productId)) {
_items.update(
productId,
(existing) => CartItem(
id: existing.id,
title: existing.title,
price: existing.price,
quantity: existing.quantity + 1),
);
} else {
_items.putIfAbsent(
productId,
() => CartItem(
id: DateTime.now().toString(),
title: title,
price: price,
quantity: 1));
}
}
}
Initialize _items variable with {} empty map.
Map<String, CartItem> _items = {};

Flutter saving Map<String, Object> to Shared Preferences

This is my Code to store CartItems.
I want to store it in Shared Preferences as cartItems since on refresh, the data are being lost.
Also I want to have function in the CartItem to check if the Product is in the cart or not so that I can make it checked/unchecked.
class CartItem {
final String id;
final String prodID;
final String title;
final String img;
final double quantity;
final double price;
final double availQuantity;
CartItem({
#required this.id,
#required this.prodID,
#required this.title,
#required this.quantity,
#required this.price,
#required this.img,
this.availQuantity,
});
}
class Cart with ChangeNotifier {
Map<String, CartItem> _items = {};
Map<String, CartItem> get items {
return {..._items};
}
int get itemCount {
return _items.length;
}
void addItem(String productId, double price, String title, String img,
double availQuantity) {
if (_items.containsKey(productId)) {
_items.update(
productId,
(existingCartItem) => CartItem(
id: existingCartItem.id,
title: existingCartItem.title,
img: existingCartItem.img,
price: existingCartItem.price,
quantity: existingCartItem.quantity + 1,
availQuantity: existingCartItem.availQuantity,
),
);
} else {
_items.putIfAbsent(
productId,
() => CartItem(
id: productId,
title: title,
img: img,
price: price,
quantity: 1,
availQuantity: availQuantity,
),
);
}
notifyListeners();
}
}
I tried many ways to convert to string and call setString(),
convert to List too. but couldn't accomplish.
Help needed.
You can store it if you convert the Map to a String as follows:
import 'dart:convert';
...
String mapToStr = json.encode(map);
When you want to get the string out of shared preferences and use it as a Map again, decode it from String to Map again as follows:
Map<String, Object> strToMap = json.decode(mapToStr);
it's possible to see your function that save in sharedPreference,
Do you have try to convert tour Cart in Map<String, dynamic> and save. I think you try to save your directly your Cart class, but it's not allowed, you can only save int, string, List, Map ...
You can check from this code, if the product is in cart or not:
bool checkProductAddedToCart(productId) {
if (_items.containsKey(productId)) {
return true;
} else {
return false;
}
}