How to pass String to constructor from a map - flutter

I'm trying to create an Athlet Object from a DocumentSnapshot. In this DocumentSnapshot I have stored a map, that holds the values(i.E. "upperbody": 0), to this athletes favourite Categorys. But for the AthleteObject I only need the key, of the category with the highest Value.
This should work, but I get the following error. And I dont' know how to rewrite this for it to not complain.
The instance member 'getFavCategory' can't be accessed in an initializer. (Documentation) Try replacing the reference to the instance member with a different expression
Athlete.fromJSON(DocumentSnapshot parsedJSON):
_name = parsedJSON["name"],
_rank = parsedJSON['rank'],
_xp = parsedJSON['xp'],
_foot = parsedJSON['foot'],
_position = parsedJSON['position'],
_statsDate = parsedJSON['statsDate'],
_challengeCount = parsedJSON['challengeCount'],
_workoutCount = parsedJSON['workoutCount'],
_favCategory = getFavCategory(parsedJSON['favCategory']),
_shotsTaken = parsedJSON['shotsTaken'],
_shotsMade = parsedJSON['shotsMade'],
_passesTaken = parsedJSON['passesTaken'],
_passesMade = parsedJSON['passesMade'];
String getFavCategory(Map<String, dynamic> map){
String favCat;
int maxVal;
map.forEach((key, value) {
if(maxVal == null || value > maxVal){
maxVal = value;
favCat = key;
}
});
return favCat;
}

Your definition of getFavCategory states that it has to be called on an initialized instance of your Athlete class (which is not a case for your constructor).
The fastest you can do is simply turn your getFavCategory function in to static (since you are not using any class variables inside):
static String getFavCategory(Map<String, dynamic> map){
String favCat;
int maxVal;
map.forEach((key, value) {
if(maxVal == null || value > maxVal){
maxVal = value;
favCat = key;
}
});
return favCat;
}

Related

The instance member 'tmpFoto' can't be accessed in an initializer. Try replacing the reference to the instance member with a different expression

My plan, I will convert from String data type to File but I get error in File coba_coba = File(foto);
part of 'models.dart';
class KirimBarangDetail extends Object {
String id, headerId, itemId, itemNama, ukuranId, ukuranNama, noBox, berat, jumlah, beratInvoice, ukuranInvoice, ukuranInvoiceNama, beratMatiPacking, jumlahMatiPacking, keterangan, foto, fotoPath, statusUpload;
File coba_coba = File(foto);
KirimBarangDetail({
this.id,this.headerId,this.itemId,this.itemNama,this.ukuranId,this.ukuranNama,this.noBox,this.berat,this.jumlah,this.beratInvoice,this.ukuranInvoice,this.ukuranInvoiceNama,this.beratMatiPacking,this.jumlahMatiPacking,this.keterangan,this.foto,this.fotoPath,this.statusUpload, this.coba_coba,
});
is there any solution with this case?
KirimBarangDetail.fromMap(Map<String, dynamic> map) {
this.id = map['id'].toString();this.headerId = map['id'].toString();this.itemId = map['item_id'].toString();this.itemNama = map['item_nama'];this.ukuranId = map['ukuran'].toString();this.ukuranNama = map['ukuran_nama'];this.noBox = map['no_box'].toString();this.berat = map['berat'].toString();this.jumlah = map['jumlah'].toString();this.beratInvoice = map['berat_invoice'].toString();this.ukuranInvoice = map['ukuran_invoice'].toString();this.ukuranInvoiceNama = map['ukuran_nama_invoice'];this.beratMatiPacking = map['berat_mati_packing'].toString();this.jumlahMatiPacking = map['jumlah_mati_packing'].toString();this.keterangan = map['keterangan'];this.foto = map['item_foto'];this.fotoPath = map['item_foto_path'];this.statusUpload = map['status_upload'];
}
Map toJson() => {
'id': id,'kbarang_id': headerId,'item_id': itemId,'ukuran': ukuranId,'no_box': noBox,'berat': berat,'jumlah': jumlah,'berat_invoice': beratInvoice,'ukuran_invoice': ukuranInvoice,'berat_mati_packing': beratMatiPacking,'jumlah_mati_packing': jumlahMatiPacking,'keterangan': keterangan,'item_foto': foto,'file_name': foto,'imgData': fotoPath,
};
}
You are initializing an instance member by other in the initializer space. You can't use other members to initialize a new member. You could do this inside the constructor or any method defined inside class.
You can take reference from here
Wrong:
class Salary{
int CTC;
int inHand = CTC*0.8; // CTC can't be used here to intialize inHand.
Salary(int CTC){
this.CTC = CTC;
}
}
Instead do like this
class Salary{
int CTC;
int inHand;
Salary(int CTC){
this.CTC = CTC;
this.inHand = this.CTC * 0.8;
}
}
Also you can do it in any other method created (but before using the inHand attribute).

class object and property variation in dart

so i recently started learning dart and I've found something kinda interesting.
why do we use constructors and getters/setters when we can achieve same results without them? (atleast when used for basic things).
class v1{
var name;
int age;
v1(this.name, this.age);
info(){
print("my name is $name and i am $age");
}
}
class v2{
var name = "bash";
int age = 100;
info(){
print("my name is $name and i am $age");
}
}
class v3{
var namee;
int agee;
String get name => namee;
int get age => agee;
set name(String name) => this.namee = name;
set age(int age) => this.agee = age;
info(){
print("my name is $name and i am $age");
}
}
void main(){
var x = v1("bash", 100);
x.info(); //my name is bash am i am 100
var z = v2();
var Z = v2();
Z.name = "vert";
Z.age = 20;
z.info(); //my name is bash and i am 100
Z.info(); //my name is vert and i am 100
var y = v3();
y.name = "rizz";
y.age = 40;
y.info(); //my name is rizz and i am 40
}
Here's a more correct version of your class:
class User {
final bool _isMale;
String _name;
int _age;
User(this._isMale, this._name, this._age);
bool isMale => _isMale;
String get name => _name;
int get age => _age;
set name(String name) {
// Sometimes you may want to update other properties here.
// For example:
// _isUpdated = true;
_name = name;
}
set age(int age) {
_age = age;
}
void info() {
print("my name is $name and i am $age");
}
}
Constructors are useful when you want to assign initial values to the class fields. They are essential if you need to assign final fields, as they are assignable only on class initialization (see _isMale field).
Setters are useful when you want to update other fields along with the field that's being modified.
Getters protect the internal state from being modified outside. In this example, nobody can change _isMale field.
You don't need to use getters and setters unless you have to.
You use getters and setters if you need to store the data in a private field, or if you want to modify it when saving or returning the value.
class Abc {
String _field;
String _otherField;
String anotherField; // No getters and setters required for this.
String get field => _field;
set field(String field) => _field = field;
String get otherField => "The value of otherField is: " + _otherField;
set otherField(String otherField) => _otherField = "[String] " + otherField;
}
As for constructors, you use them to initialize the object with custom values. When you need to work with immutable objects (which use final variables), you'll have to use constructors to set their initial value. You can also modify the incoming value according to your need before storing it,
class Def {
final field; // Dart generates getters for this field, but it's value can't be modified once the object is instantiated.
final _otherField; // No getters for this.
Def(String field, String otherField) {
this.field = "[String] $field"
this._otherField = "[String] $otherField"
}
String describeMe() {
return "[Def]: field: $field, _otherField: $_otherField"
}
}

How to compare the type variable in "is" operator in Dart

I couldn't find a way to store the Type value in Map so that I could use it in is operator to check the validity of type using this map later on. Also, can is operator accept Type as a variable?
For eg, Below is hypothetical code solving the problem but it's invalid.
Map<String, Type> map = {
"sku": String,
"price": double,
"quantity": int,
};
dynamic value = 10;
if(value is map["quantity"]){
print("value is of type int and int is expected for quantity value");
}
You can do something like this:
class TypeCheck<T> {
const TypeCheck();
bool typeCheck(dynamic value) => value is T;
}
void main() {
Map<String, TypeCheck> map = {
"sku": TypeCheck<String>(),
"price": TypeCheck<double>(),
"quantity": TypeCheck<int>(),
};
dynamic value = 10;
if (map["quantity"]!.typeCheck(value)) {
print("value is of type int and int is expected for quantity value");
}
}
Im not sure I fully understand I understand what you are trying to do but why don't you try something like.
bool _validate(Map productDetails){
if (productDetails.containsKey("sold_individually") && productDetails["sold_individually"] is bool) {
//return true or false
}
else if (productDetails.containsKey("stock_quantity") && productDetails["stock_quantity"] is int){
//return true or false
}
else if (productDetails.containsKey("tax_class") && productDetails["tax_class"] is String && productDetails["tax_class"].isNotEmpty) {
//return true or false
} else {
//return true or false
}
}
As for the other part of your question you wont get an error but you will always return false. In contrast if you check if a variable is dynamic it will always return true.
I don't really understand your end goal. But from what you have, I don't think you are taking advantage of the strongly-typed nature of dart.
Assuming you are getting your map from an API, you could enforce
typing manually in your code as follows;
Map<String, Type> map = {
"sku": json['key'] as String,
"price": json['key'] as double,
"quantity": json['key'] as int,
};
And avoid using dynamic when declaring variables.
OR
In the case you have a user-defined type you what to compare, you can use the equatable package on a class for instance as follows;
class CustomMap extends Equatable {
String sky;
double price;
int quantity;
// here you put the fields of a class you want for two instances of a class to be equal.
#overide
List<Object> get props => [sky, price, quantity];
}
Update from your comment
You should have a custom class for the API objects for instance;
class Item extends Equatable {
String sku;
double price;
int quantity;
Item({this.sky, this.price, this.quantity});
// factory constructor
factory Item.fromMap(Map<String, dynmic> json) {
final sku = json['sku'] as String,
final price = (json['price'] as num) as double,
final quantity = json['quantity'] as num,
return Item(sku: sku, price: price, quantity: quantity);
}
// define equatable objects
#override
List<Object> get props => [sku, price, quantity];
}
Now you can use it as follows;
Future<Item> objectsFromService(Map<String, dynamic> json ) async {
http.Response response = http.get(url);
if(response.status == 200) {
final decodedJson = json.decode(response.body);
return Item.fromJson(decodedJson);
}else{
print('Error fetch data');
return null;
}
}
Hope it helps

how to get a string for a class property name in dart?

i want to do use the model's properties such as:
Animal.id as a param to a function or use some extension method to be able to "id". similarly, i'd like to use Animal.title in that way to get "title" as a returned value. how could i do this with my class to get a string for any given property name?
int _id;
String _title;
Animal(this._id, this._title);
int get id => _id;
String get title => _title;
}
the usage case is being able to query without having autocomplete on my model's property names in a string for sql querying:
List<Map> results = await db.query("Animal",
columns: Set. ["id", "title"],
where: 'id = ?',
whereArgs: [id]);
Using the dart:mirrors package you can dynamically access your class properties and invoke methods using their string names.
https://api.dart.dev/stable/2.4.0/dart-mirrors/dart-mirrors-library.html
import 'dart:mirrors';
class Animal {
int _id;
String _title;
Animal(this._id, this._title);
int get id => _id;
String get title => _title;
}
main() {
var r = reflect(Animal(1, 'Dog'));
print(r.getField(Symbol('id')).reflectee);
print(r.getField(Symbol('title')).reflectee);
}
import 'dart:mirrors';
class MyClass {
int i, j;
void my_method() { }
int sum() => i + j;
MyClass(this.i, this.j);
static noise() => 42;
static var s;
}
main() {
MyClass myClass = new MyClass(3, 4);
InstanceMirror myClassInstanceMirror = reflect(myClass);
ClassMirror MyClassMirror = myClassInstanceMirror.type;
InstanceMirror res = myClassInstanceMirror.invoke(#sum, []);
print('sum = ${res.reflectee}');
var f = MyClassMirror.invoke(#noise, []);
print('noise = $f');
print('\nMethods:');
Iterable<DeclarationMirror> decls =
MyClassMirror.declarations.values.where(
(dm) => dm is MethodMirror && dm.isRegularMethod);
decls.forEach((MethodMirror mm) {
print(MirrorSystem.getName(mm.simpleName));
});
print('\nAll declarations:');
for (var k in MyClassMirror.declarations.keys) {
print(MirrorSystem.getName(k));
}
MyClassMirror.setField(#s, 91);
print(MyClass.s);
}
the output:
sum = 7
noise = InstanceMirror on 42
Methods:
my_method
sum
noise
All declarations:
i
j
s
my_method
sum
noise
MyClass
91

Dart model throws error when mixing many data types

I made this simple model to work with an API
class BooksModel {
List<_Book> _books = [];
BooksModel.fromJson(Map<dynamic, dynamic> parsedJson) {
List<_Book> temp = [];
for (int i = 0; i < parsedJson['books'].length; i++) {
_Book book = _Book(parsedJson['books'][i]);
temp.add(book);
}
_books = temp;
}
List<_Book> get books => _books;
}
class _Book {
int _id;
String _name;
_Book(book) {
_id = book['id'];
_name = book['name'];
}
int get id => _id;
int get name => _name;
}
The problem is i have to turn all '_Book' class properties to 'String', if i made only one 'int' as given in the above example, it throws this error.
type 'String' is not a subtype of type 'int'
I don't even use that 'id' which is 'int' in my app, so it's not about the usage of it, the problem is in this model
Can you just show the example of your json, so that i can tell you that what your model should be or where it is going wrong.
So maybe your issue is not that big , id required is integer and you are passing the String.
Is book['id'] a string?
Try it:
// _id = book['id'];
_id = int.parse(book['id']);