The argument type 'Object?' can't be assigned to the parameter type 'Map<dynamic, dynamic>'. GetX - flutter

so basically i'm frustrated by this 'Object?' type, i already tried t change its type in core file but i was worried to cause a weird behavior in the future. heres my code any kind of help will be appreciated
class HomeViewModel extends GetxController{
List<CategoryModel> get categorymodel => _categorymodel;
late DocumentSnapshot doc;
List<CategoryModel> _categorymodel = [];
final CollectionReference _categoryCollectionRef =
FirebaseFirestore.instance.collection('categories');
HomeViewModel(){
getCategory();
}
getCategory()async{
_categoryCollectionRef.get().then((value) {
for(int i = 0; i<value.docs.length;i++){
_categorymodel.add(CategoryModel.fromJson(value.docs[i].data()));
}
});
}
}
and this one is from my model class:
class CategoryModel {
late String name, image;
CategoryModel({required this.name, required this.image});
CategoryModel.fromJson(Map<dynamic, dynamic> map) {
if (map == null) {
return;
}
name = map['name'];
image = map['image'];
}
toJson() {
return {
'name': name,
'image': image,
};
}
}

You need to specify the type of data you're expecting from the DocumentSnapshot.
Change this line:
_categorymodel.add(CategoryModel.fromJson(value.docs[i].data()));
to this:
_categorymodel.add(CategoryModel.fromJson(value.docs[i].data() as Map<String, dynamic>));
Check out the guide for migration to cloud_firestore 2.0.0.

Related

Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Map<String, double>'

I have an object I am wanting to save to local storage, but whenever I write that object to storage I get the error shown in the title.
Here's the full stack trace
[VERBOSE-2:ui_dart_state.cc(198)] Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Map<String, double>' in type cast
#0 new Product.fromJson (package:app/src/objects/product.dart:27:47)
#1 new ShoppingListProduct.fromJson (package:app/src/objects/shopping_list_product.dart:18:29)
#2 ShoppingListHandler.readShoppingListProducts.<anonymous closure> (package:app/src/handlers/shopping_list_handler.dart:65:38)
#3 MappedListIterable.elementAt (dart:_internal/iterable.dart:413:31)
#4 ListIterator.moveNext (dart:_internal/iterable.dart:342:26)
#5 new _GrowableList._ofEfficientLengthIterable (dart:core-patch/growable_array.dart:189:27)
#6 new _GrowableList.of (dart:core-patch/growable_array.dart:150:28)
#7 new List.of (dart:core-patch/array_patch.dart:51:28)
And here's the handler class which is used for writing, reading, and updating the shoppingListProduct class.
class ShoppingListHandler {
ShoppingListHandler._privateConstructor();
static final ShoppingListHandler instance = ShoppingListHandler._privateConstructor();
static File? _file;
static const _fileName = 'shopping_list_file.txt';
// Get the data file
Future<File> get file async {
if (_file != null) return _file!;
_file = await _initFile();
return _file!;
}
// Initialize file
Future<File> _initFile() async {
final _directory = await getApplicationDocumentsDirectory();
final _path = _directory.path;
// Check if file exists
File file = File('$_path/$_fileName');
if(await file.exists() == false){
await file.create(recursive: true);
}
return file;
}
// Users
static Set<ShoppingListProduct> _shoppingListSet = {};
Future<void> writeShoppingList(ShoppingListProduct shoppingListProduct) async {
final File fl = await file;
_shoppingListSet.add(shoppingListProduct);
// Now convert the set to a list as the jsonEncoder cannot encode
// a set but a list.
final _shoppingListMap = _shoppingListSet.map((e) => e.toJson()).toList();
await fl.writeAsString(jsonEncode(_shoppingListMap));
}
Future<List<ShoppingListProduct>> readShoppingListProducts() async {
final File fl = await file;
final _content = await fl.readAsString();
List<dynamic> _jsonData = [];
if(_content.isNotEmpty){
_jsonData = jsonDecode(_content);
}
final List<ShoppingListProduct> _shoppingListProducts = _jsonData
.map(
(e) => ShoppingListProduct.fromJson(e as Map<String, dynamic>),
)
.toList();
return _shoppingListProducts;
}
Future<void> deleteShoppingListProduct(ShoppingListProduct shoppingListProduct) async {
final File fl = await file;
_shoppingListSet.removeWhere((e) => e == shoppingListProduct);
final _shoppingListMap = _shoppingListSet.map((e) => e.toJson()).toList();
await fl.writeAsString(jsonEncode(_shoppingListMap));
}
Future<void> updateShoppingListProduct({
required String key,
required ShoppingListProduct updatedShoppingListProduct,
}) async {
_shoppingListSet.removeWhere((e) => e.ID == updatedShoppingListProduct.ID);
await writeShoppingList(updatedShoppingListProduct);
}
}
the shoppingListProduct class only has 3 parameters.
an ID which is just an integer.
a Product parameter which is a Product object from the Product class.
and a ticked boolean.
I believe the problem is that inside the Product class I have a "price" object which is a map with a string and a double.
Here's the product class.
class Product extends Equatable{
const Product({
required this.user,
required this.id,
required this.name,
required this.image,
required this.brandName,
required this.productPrices,
});
final String user;
final int id;
final String name;
final String image;
final String brandName;
final Map<String, double> productPrices;
Product.fromJson(Map<String, dynamic> map)
: user = (map['user'] as String),
id = (map['id'] as int ).toInt(),
name = (map['name'] as String),
image = (map['image'] as String),
brandName = (map['brandName'] as String),
productPrices = (map['productPrices'] as Map<String, double>);
Map<String, dynamic> toJson(){
return {
'user': user,
'id': id,
'name': name,
'image': image,
'brandName': brandName,
'productPrices': productPrices,
};
}
#override
String toString(){
return 'Product:\n\tId: $id\n\tName: $name\n\tImage: $image\n\tBrandName: $brandName\n\tProductPrices: $productPrices';
}
#override
List<Object> get props => [id, name, image, brandName, productPrices];
}
And here's the shoppingListProduct class which is used in the saving process.
class ShoppingListProduct extends Equatable {
ShoppingListProduct({
required this.ID,
required this.product,
required this.ticked,
});
final int ID;
final Product product;
late bool ticked;
ShoppingListProduct.fromJson(Map<String, dynamic> map)
: ID = (map['ID'] as int).toInt(),
product = Product.fromJson(map['product']),
ticked = (map['ticked'] as bool);
Map<String, dynamic> toJson() {
return {
'ID': ID,
'product': product,
'ticked': ticked,
};
}
#override
String toString() {
return 'ShoppingListProduct:\n\tID: $ID\n\tProduct: $product\n\tTicked: $ticked';
}
#override
List<Object> get props => [ID, product, ticked];
}
In Dart, type parameters are preserved at runtime and are considered during type checks. So a Map<String, dynamic> is not a subtype of Map<String, double> and cannot be cast to it, which is the error that you're seeing here.
Since the JSON parser in Dart can't know the right type of the map beforehand, all JSON objects are parsed as a Map<String, dynamic>. Since you're sure that the map will only contain doubles as values, you can use (map['productPrices'] as Map<String, dynamic>).cast<String, double>() in the fromJson constructor instead.
The cast method on map will return a view over the original map. This view will do casts during lookups instead of for the whole map you did it with the as operator.

The argument type 'ProductModel?' can't be assigned to the parameter type 'ProductModel'

I'm making a midel to upload product image,price and name to firebase then i face this error (The argument type 'ProductModel?' can't be assigned to the parameter type 'ProductModel'.)
class ProductProvider with ChangeNotifier {
List<ProductModel> pizzaProductList = [];
ProductModel? productModel;
fatchPizzaproductData() async {
// List<ProductModel> newList = [];
QuerySnapshot value =
await FirebaseFirestore.instance.collection("PizzaProducts").get();
pizzaProductList = value.docs.map((element) {
return ProductModel(
productImage: element.get("productImage"),
productName: element.get("productName"),
productPrice: element.get("productPrice"),
);
}).toList();
}
get getPizzaproductDataList {
return pizzaProductList;
}
}
The problem is that productModel is a nullable type, whereas pizzaProduct is a List of non-nullable ProductModels.
Instead of storing a property productModel on your class, consider mapping directly from value.docs to pizzaProduct, and removing the intermediate step of storing the model in productModel:
class ProductProvider with ChangeNotifier {
List<ProductModel> pizzaProduct = [];
Future<void> fetchPizzaProductData() async {
QuerySnapshot value =
await FirebaseFirestore.instance.collection("PizzaProducts").get();
pizzaProduct = value.docs.map((element) {
return ProductModel(
productImage: element.get("productImage"),
productName: element.get("productName"),
productPrice: element.get("productPrice"),
);
}).toList();
// Since this is a ChangeNotifier, I'm assuming you might want to
// notify listeners when `pizzaProduct` changes. Disregard this line
// if that's not the case.
notifyListeners();
}
}

The argument type 'Object?' can't be assigned to the parameter type 'Map<dynamic, dynamic>'

I have an error on the "snap.snapshot.value" parameter in the following line "var map = Map <String, dynamic> .from (snap.snapshot.value);". The error is "The argument type 'Object?' can't be assigned to the parameter type 'Map <dynamic, dynamic>'. "
class _HomePageState extends State<HomePage> {
List<Posts> postsList = [];
#override
void initState() {
super.initState();
DatabaseReference postsRef = FirebaseDatabase.instance.reference().child("Posts");
postsRef.once().then((snap) {
var map = Map<String, dynamic>.from(snap.snapshot.value); <--- the error is here
postsList.clear();
map.forEach((key, value) {
var values = Map<String,dynamic>.from(map);
Posts posts = Posts
(
values['url'],
values['descrizione'],
values['data'],
values['ora']
);
postsList.add(posts);
});
Would you change a code like below?
From
var map = Map<String, dynamic>.from(snap.snapshot.value);
To
Map<String, dynamic> map = snap.snapshot.value as Map<String, dynamic>
This is because Map.from function accepts a Map<dynamic, dynamic> but you are passing the object instead. So to pass as the same use casting like below :
var map = Map<String, dynamic>.from(snap.snapshot.value as Map<dynamic, dynamic>);
In your Posts model, you need to remove any explicit object casting.
e.g. change from
`Posts.fromMap(Map<String, dynamic> map) {
comments: List<String>.from((map['comments'] as List<String>))
}`
to
`Posts.fromMap(Map<String, dynamic> map) {
comments: List<String>.from((map['comments'] as List))
}`
so it's cast as a List and no farther

_TypeError (type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>') in flutter

Hello I am making an api call where I am getting array of banners. I am getting below error -
_TypeError (type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>')
banners_bloc.dart
class BannersBloc {
late BannerRepository _bannerRepository;
late StreamController _streamController;
StreamSink get bannerListSink => _streamController.sink;
BannersBloc() {
_streamController = StreamController();
_bannerRepository = BannerRepository();
fetchBanners();
}
fetchBanners() async {
bannerListSink.add('Fetching Banners');
try {
Banners banners = await _bannerRepository.getBanners();
bannerListSink.add(banners);
} catch (e) {
bannerListSink.add(e.toString());
print(e);
}
}
dispose() {
_streamController.close();
}
}
banners.dart
class Banners {
late String bannerImageUrl;
late String bannerImageAlt;
late bool isActive;
late int order;
late String id;
Banners(
{required this.bannerImageUrl,
required this.bannerImageAlt,
required this.isActive,
required this.order,
required this.id});
Banners.fromJson(Map<String, dynamic> json) {
bannerImageUrl = json['bannerImageUrl'];
bannerImageAlt = json['bannerImageAlt'];
isActive = json['isActive'];
order = json['order'];
id = json['id'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['bannerImageUrl'] = this.bannerImageUrl;
data['bannerImageAlt'] = this.bannerImageAlt;
data['isActive'] = this.isActive;
data['order'] = this.order;
data['id'] = this.id;
return data;
}
}
api_base_helper.dart
class APIHelper {
final String _baseURL =
"https://raw.githubusercontent.com/gautam-in/shopping-cart-assignment/master/server/";
Future<dynamic> get(String url) async {
try {
final response = await http.get(Uri.parse(_baseURL + url));
return json.decode(response.body);
} catch (err) {
throw new Exception("Something went wrong");
}
}
}
get_banners.dart
class BannerRepository {
Future getBanners() async {
final response = await new APIHelper().get("banners/index.get.json");
return Banners.fromJson(response);
}
}
If your response from the API is a List of Banners, then the error is being thrown by getBanners. As the fromJson method is expecting a of type Map<String, dynamic>. To solve this you'll need to iterate through the response and call Banners.fromJson for each item in the response list.
class BannerRepository {
Future<List<Banners>> getBanners() async {
final response = await new APIHelper().get("banners/index.get.json");
// Sample Code, handler errors and other stuff
return response.map((e) =>Banners.fromJson(e)).toList();
}
}

A value of type 'Rx<Future<List<SectionsDBStat>>*>*' can't be assigned to a variable of type

I am learning Flutter and GetX.
I have got Model:
class SectionsDBStat {
int notificationsTotalCount;
int notificationsWaitingForProcessing;
DateTime notificationsLastArchiveDate;
SectionsDBStat({
required this.notificationsTotalCount,
required this.notificationsWaitingForProcessing,
required this.notificationsLastArchiveDate
});
factory SectionsDBStat.fromJson(Map<String, dynamic> json) {
return SectionsDBStat(
notificationsTotalCount: json['notificationsTotalCount'],
notificationsWaitingForProcessing: json['notificationsWaitingForProcessing'],
notificationsLastArchiveDate: DateTime.parse(json['notificationsLastArchiveDate'])
);
}
}
I am trying to create Getx contoller that receive data from http:
class SectionsStatController extends GetxController {
SectionsDBStat sectionsDBStat = Future.value(<SectionsDBStat>).obs;
getStat() async {
var value = await http.get('${url}/stat?total');
if(value.statusCode == 200) {
Map<String, dynamic> valueMap = jsonDecode(value.body)['data'];
sectionsDBStat = SectionsDBStat.fromJson(valueMap);
update();
} else {
print("Can't get stat: ${value.statusCode}");
}
}
}
I am getting an error:
A value of type 'Rx<Future<List<SectionsDBStat>>*>*' can't be assigned to a variable of type 'SectionsDBStat'.
So I should use another type. But what? I tried final but got error:
'sectionsDBStat' can't be used as a setter because it's final.
I don't know why are you using Future, here you are trying to assign Rx<Future<List<SectionsDBStat>>*> to sectionsDBStat and that is not possible
Replace this line
SectionsDBStat sectionsDBStat = Future.value(<SectionsDBStat>).obs;
with this
final sectionsDBStat = SectionsDBStat().obs;
and then assign it like this
sectionsDBStat.value = SectionsDBStat.fromJson(valueMap);