dart null safety class initialization - flutter

I built two classes.
first class is the video Class.
second class is Player Class.
And one of Player variables is list of video class
and after dart null safety it is not allowed to add null varaiables
I should add initialization value to the class ( I don't want to add required ).
First Class - Video
import 'dart:convert';
VideoModel videoModelFromJson(String str) =>
VideoModel.fromJson(json.decode(str));
String videoModelToJson(VideoModel data) => json.encode(data.toJson());
class VideoModel {
VideoModel({
this.playerVideoId = -1,
this.playerIdId = -1,
this.videoLink = "Please Upload",
});
int playerVideoId;
int playerIdId;
String videoLink;
factory VideoModel.fromJson(Map<String, dynamic> json) => VideoModel(
playerVideoId: json["playerVideoId"],
playerIdId: json["playerId_id"],
videoLink: json["videoLink"],
);
Map<String, dynamic> toJson() => {
"playerVideoId": playerVideoId,
"playerId_id": playerIdId,
"videoLink": videoLink,
};
}
Second Class which contain error in defining videos
// To parse this JSON data, do
//
// final playerBasic = playerBasicFromJson(jsonString);
import 'dart:convert';
import 'package:sportive/pages/player/Model/Video_Model.dart';
PlayerBasic playerBasicFromJson(String str) =>
PlayerBasic.fromJson(json.decode(str));
String playerBasicToJson(PlayerBasic data) => json.encode(data.toJson());
class PlayerBasic {
PlayerBasic({
this.playerId = -1,
this.userIdId = -1,
this.playerFirstName = "",
this.playerLastName = "",
this.nationality = "",
this.birthday = "",
this.height = -1,
this.weight = -1,
this.currentCountry = "",
this.currentCity = "",
this.game = "",
this.image = "",
this.gender = "Male",
this.videos, // Error here Parameter The parameter 'videos' can't have a value of 'null' because of its type, but the implicit default value is 'null'.
//Try adding either an explicit non-'null' default value or the 'required' modifier
});
int playerId;
int userIdId;
String playerFirstName;
String playerLastName;
String nationality;
String birthday;
int height;
int weight;
String currentCountry;
String currentCity;
String game;
String image;
String gender;
List<VideoModel> videos;
factory PlayerBasic.fromJson(Map<String, dynamic> json) => PlayerBasic(
playerId: json["playerId"],
userIdId: json["userId_id"],
playerFirstName: json["playerFirstName"],
playerLastName: json["playerLastName"],
nationality: json["nationality"],
birthday: json["birthday"],
height: json["height"],
weight: json["weight"],
currentCountry: json["currentCountry"],
currentCity: json["currentCity"],
game: json["game"],
image: json["image"],
gender: json['gender'],
videos: json['videos'],
);
Map<String, dynamic> toJson() => {
"playerId": playerId,
"userId_id": userIdId,
"playerFirstName": playerFirstName,
"playerLastName": playerLastName,
"nationality": nationality,
"birthday": birthday,
"height": height,
"weight": weight,
"currentCountry": currentCountry,
"currentCity": currentCity,
"game": game,
"image": image,
"gender": gender,
"videos": videos,
};
}
Sorry Iam Flutter beginner question.

Just change the videos declaration to
List<VideoModel>? videos;
Let's suppose you have this class and you want to provide a default value for bar in the constructor:
class Foo {
List<int> bar;
}
If you want to be able to modify bar later:
class Foo {
// Use this
Foo({List<int>? bar}) : bar = bar ?? [];
List<int> bar;
}
void main() {
Foo foo;
foo = Foo();
print(foo.bar);
// Outputs []
foo.bar.add(4);
print(foo.bar);
// Outputs [4]
foo = Foo(bar: [1, 2, 3]);
print(foo.bar);
// Outputs [1, 2, 3]
foo.bar.add(4);
print(foo.bar);
// Outputs [1, 2, 3, 4]
}
If you want to keep bar immutable (i.e. you won't use methods such as add or remove):
class Foo {
// Use this
Foo({this.bar = const []});
List<int> bar;
}
void main() {
Foo foo;
foo = Foo();
print(foo.bar);
// Outputs []
// foo.bar.add(4);
// It'll throw Uncaught Error: Unsupported operation: add
foo = Foo(bar: [1, 2, 3]);
print(foo.bar);
// Outputs [1, 2, 3]
foo.bar.add(4);
print(foo.bar);
// Outputs [1, 2, 3, 4]
}

Related

how to sum list values from API in flutter

Does anyone here know/have references/examples of how to add up the values in the list in Flutter. Thanks
use sum:
import 'package:collection/collection.dart';
void main() {
final list = [1, 2, 3, 4];
final sum = list.sum;
print(sum); // prints 10
}
Your question is similar to the question here, refer to it for more information
you can use .fold() method
fold method:
T fold<T>(T initialValue, T Function(T, Data) combine)
example for sum list of object:
void main() {
List<Data> listData = [
Data(count: 10, name: 'a'),
Data(count: 12, name: 'bc'),
Data(count: 21, name: 'abc'),
];
int sum = listData.fold(0, (int preValue, data) => preValue + data.count);
print(sum);// 43
}
class Data {
int count;
String name;
Data({required this.count, required this.name});
}

Reorder Array of objects Flutter

Array of object
Input:
[
{id:1,order:1},
{id:2,order:null},
{id:3,order:0},
{id:4,order:null},
{id:5,order:3}
]
Output:
[
{id:3,order:0},
{id:1,order:1},
{id:2,order:null},
{id:5,order:3},
{id:4,order:null}
]
Considering model
Item(int id,int? Order)
By default the order is null and these positions are to be maintained and object having orders are to be moved up or down.
Try this, if the array is of type Map -
arrayOfObjects.sort((a, b) => a['order'].compareTo(b['order']));
Or this if it is holding Item class with an order attribute
arrayOfObjects.sort((Item a, Item b) => a.order.compareTo(b.order));
Note - You can remove items with null order before running the sort.
Example
arrayOfObjects.removeWhere((item)=> item.order == null);
The double Iterations are based on the length of the array to handle the nulls.
Solution
import 'package:collection/collection.dart';
class Item {
int? _id;
int? _order;
Item({int? id, int? order}) {
this._id = id;
this._order = order;
}
int? get id => _id;
set id(int? id) => _id = id;
int? get order => _order;
set order(int? order) => _order = order;
Item.fromJson(Map<String, dynamic> json) {
_id = json['id'];
_order = json['order'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this._id;
data['order'] = this._order;
return data;
}
}
List<Item> reorder(List<Item> it){
var tempData = it;
tempData.forEach((_){
tempData.forEachIndexed((index,val){
///Remove original and replace
var ind = val.order;
if(ind!=null){
///Check if it is at the Proper Position
if (index == ind) {
return;
}
var first = it.removeAt(index);
it.insert(ind as int, first);
}
});
});
return it;
}
void main() {
var list = [
Item(id: 1, order: 1),
Item(id: 3, order: 2),
Item(id: 2, order: 7),
Item(id: 4, order: null),
Item(id: 5, order: null),
Item(id: 6, order: null),
Item(id: 7, order: 6),
Item(id: 8, order: 4)
];
list.forEach((it) => print('${it.id} ->${it.order}'));
var first = reorder(list);
print('\n');
first.forEach((it) => print('${it.id} ->${it.order}'));
///Stack List
}

Flutter Dart The getter '' was called on null

I'm sending response.body and country name with slash as like germany/ as parameter and converting it to Germany in parser and returning. But if i use parameter, i'm getting error of the getter 'vacTotal' was called on null. If i write "Germany"to countryDataVac["Germany"] the code works correctly. Is it the problem on {"Global": new CountryDataVac()}? The default value is "Global".
main.dart:
Map<String, CountryDataVac> countryDataVac = {"Global": new CountryDataVac()};
static Map<String, CountryDataVac> getCountryDataVac(String body, var countryname) {
Map<String, CountryDataVac> countryDataVac = {};
responseVac1Day = await http.get("https://disease.sh/v3/covid-19/vaccine/coverage?fullData=true&lastdays=1"); //vaccine number info
countryDataVac = Parser.getCountryDataVac(responseVac1Day.body, "germany/"); //vaccine number info
Parser.dart:
var usera = CountryDataVac.fromJson(jsonDecode(result));
countryDataVac[capitalize(countryname).replaceAll("/", "")] = parseRowVac(usera.vacTotal,usera.vacDaily,usera.vactotalPerHundred,usera.vacdailyPerMillion); //gives 'germany/' as 'Germany' but getting error if i get the countryname by parameter
countryDataVac["Germany"] = parseRowVac(usera.vacTotal,usera.vacDaily,usera.vactotalPerHundred,usera.vacdailyPerMillion); //works
}
CountryDataVac.dart (created by json to dart)
import 'dart:convert';
List<CountryDataVac> countryDataVacFromJson(String str) => List<CountryDataVac>.from(json.decode(str).map((x) => CountryDataVac.fromJson(x)));
String countryDataVacToJson(List<CountryDataVac> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class CountryDataVac {
CountryDataVac({
this.vacTotal = 0,
this.vacDaily = 0,
this.vactotalPerHundred = 0,
this.vacdailyPerMillion = 0,
this.date = "",
});
int vacTotal = 0;
int vacDaily = 0;
int vactotalPerHundred = 0;
int vacdailyPerMillion = 0;
String date = "";
factory CountryDataVac.fromJson(Map<String, dynamic> json) => CountryDataVac(
vacTotal: json["total"],
vacDaily: json["daily"],
vactotalPerHundred: json["totalPerHundred"],
vacdailyPerMillion: json["dailyPerMillion"],
date: json["date"],
);
Map<String, dynamic> toJson() => {
"total": vacTotal,
"daily": vacDaily,
"totalPerHundred": vactotalPerHundred,
"dailyPerMillion": vacdailyPerMillion,
"date": date,
};
}
use
countryname.replaceFirst(countryname[0], countryname[0].toUpperCase()).replaceAll("/", "");
instead of
capitalize(countryname).replaceAll("/", "")
i think there is something wrong with your capitalize method

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 insert a List<Class> into a Map<String, dynamic> in dart?

My problem is that I have a list of the following class:
class ingreso_Egreso_Dummy{
int tipo;
String monto;
String moneda;
String descripcion;
}
then I want to insert the data into a Map which later will be converted into a json and which I am creating like this:
Map<String, dynamic> body;
body = {
"Cod_Prom": "01",
"CodCli": "003526",
"Status": _index_status.toString(),
"NOMBRE": controller_nombre.text,
"APELLIDOS": controller_apellidos.text,
"solicitud":[{
"Cod_Solicit": 1.toString(),
"Fecha": DateFormat("y-d-M").format(DateTime.now()),
"Status_Solicit": "E",}],
"prestamo":[{
"Monto_Solicit":controller_monto_solic.text,
"Plazo":controller_plazo.text,
"Cod_TipoPlazo":_index_tipoplazo.toString(),
"Nombre_Resp":controller_nombreresp.text,
"Telf_Resp":controller_telefonoresp.text,}],
"Ingresos": [{
//// here I want create a loop that returns a map for each value
//// of the list like this:
//// "Descripcion": Listaingresos[i].descripcion;
})
}]
};
Every help is very appreciated, thank you.
// camelCaseStyle is a standard for class names for Dart
class IngresoEgresoDummy {
int tipo;
String monto;
String moneda;
String descripcion;
Map<String, dynamic> toJson(){
return {
'tipo': tipo,
'monto': monto,
'monedo': moneda,
'descripcion': descripcion
};
}
}
and after that
List<IngresoEgresoDummy> listaingresos= List();
Map<String, dynamic> body = {
// all your params
"Ingresos": listaingresos.map((ingreso) => ingreso.toJson()).toList()
// all your params
};