Dart/Flutter Problem with calling factory constructor of a model - flutter

I have a model class for Inbox which contains a normal constructor and a factory constructor that accepts a list. Everything seems to work except after calling the factory constructor the code does not continue to the next line. _inbox = Inbox.fromList(_fetchInboxResBody['inbox']);
Here is the code where I called the Inbox's factory constructor
import 'package:flutter/foundation.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';
import '../models/inbox.dart';
class InboxProvider with ChangeNotifier {
final _rootUrl = 'http://localhost:8080';
// final _rootUrl = 'http://firstcarestartup.appspot.com';
//inbox as an array
Map<String, dynamic> _fetchInboxResBody;
Map<String, dynamic> _fetchInboxResError;
Inbox _inbox;
//getters
Inbox get inbox => _inbox;
Map<String, dynamic> get fetchInboxResError => _fetchInboxResError;
fetchInbox(String accessToken) async {
print('fetching inbox');
try {
var response = await http.get('$_rootUrl/customer/inbox', headers: {
'Content-Type': 'application/json',
'Authorization': 'bearer $accessToken'
});
_fetchInboxResBody = json.decode(response.body);
if (_fetchInboxResBody.containsKey('error')) {
_fetchInboxResError = _fetchInboxResBody;
notifyListeners();
} else {
_fetchInboxResError = null;
print('yeah1');
_inbox = Inbox.fromList(_fetchInboxResBody['inbox']);
print('yeah');
notifyListeners();
}
} catch (e) {
_fetchInboxResError = {'error': e.toString()};
notifyListeners();
}
}
}
And here is inbox.dart
import 'package:flutter/material.dart';
class Inbox {
List<Message> messages;
int unread;
Inbox({#required this.messages, #required this.unread});
factory Inbox.fromList(List response) {
int counter = 0;
List msgs = new List();
response.forEach((f) {
if(f['read'] == false){
counter++;
}
Message msg = Message.fromMap(f);
msgs.add(msg);
});
print(msgs[2].content);
return new Inbox(messages: msgs, unread: counter);
}
}
class Message {
String content;
String date;
String header;
String id;
String imageUrl;
bool read;
String type;
Message(
{#required this.content,
#required this.date,
#required this.header,
#required this.id,
this.imageUrl,
#required this.read,
this.type});
factory Message.fromMap(Map messageMap) {
var content = messageMap['content'];
var date = messageMap['date'];
var header = messageMap['header'];
var id = messageMap['id'];
var imageUrl = messageMap['image'] ?? null;
var read = messageMap['read'];
var type = messageMap['type'];
return new Message(content: content, date: date, header: header, id: id, read: read, imageUrl: imageUrl, type: type);
}
}

Related

Database empty flutter

I'm getting empty string when I trying to get the titles. Please help me.
Here's my source code
Here's my task.dart file
// task.dart
class Task {
int? id;
String? title;
String? note;
int? isCompleted;
String? date;
String? startTime;
String? endTime;
int? color;
int? remind;
String? repeat;
Task({
this.id,
this.title,
this.note,
this.isCompleted,
this.date,
this.startTime,
this.endTime,
this.color,
this.remind,
this.repeat,
});
Task.fromJson(Map<String, dynamic> json) {
id = json['id'];
title = json['title'];
note = json['note'];
isCompleted = json['isCompleted'];
date = json['date'];
startTime = json['startTime'];
endTime = json['endTime'];
color = json['color'];
remind = json['remind'];
repeat = json['repeat'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic> ();
data['id'] = this.id;
data['title'] = this.title;
data['note'] = this.note;
data['isCompleted'] = this.isCompleted;
data['date'] = this.date;
data['startTime'] = this.startTime;
data['endTime'] = this.endTime;
data['color'] = this.color;
data['remind'] = this.remind;
data['repeat'] = this.repeat;
return data;
}
}
Here's my task_controller.dart file
import 'package:calendar_app/db/db_helper.dart';
import 'package:calendar_app/models/task.dart';
import 'package:get/get.dart';
// task_controller.dart
class TaskController extends GetxController {
#override
void onReady() {
getTasks();
super.onReady();
}
var taskList = <Task>[].obs;
Future<int> addTask({Task? task}) async{
return await DBHelper.insert(task);
}
void getTasks() async {
List<Map<String, dynamic>> tasks = await DBHelper.query();
taskList.assignAll(tasks.map((data) => new Task.fromJson(data)).toList());
}
}
db_helper.dart
import 'package:calendar_app/models/task.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart';
import 'dart:developer' as devtools show log;
// db_helper.dart
class DBHelper {
static Database? _db;
static final int _version = 1;
static final String _tableName = 'Tasks';
static Future<void> initDb() async {
if (_db != null) {
return;
}
try {
String _path = await getDatabasesPath() + 'tasks.db';
_db = await openDatabase(
_path,
version: _version,
onCreate: (db, version) {
devtools.log('Creating a new one');
return db.execute(
"CREATE TABLE $_tableName("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"title STRING, note TEXT, date STRING, "
"startTime STRING, endTime STRING, "
"remind INTEGER, repeat STRING, "
"color INTEGER, "
"isCompleted INTEGER)",
);
},
);
} catch (e) {
devtools.log(e.toString());
}
}
static Future<int> insert(Task? task) async {
devtools.log('Insert func called');
return await _db?.insert(_tableName, task!.toJson()) ?? 1;
}
static Future<List<Map<String, dynamic>>> query() async {
devtools.log('Query func called');
return await _db!.query(_tableName);
}
}
When I trying to get a print statement of title it return empty. I have no idea what's happening here. Please help me.
print(_taskController.taskList[index].note.toString());
I'm following dbstech tutorial. If anyone have the source code please let me know.
First in getTask function try to reset taskList by calling this:
void getTasks() async {
taskList = []; // <--- add this
List<Map<String, dynamic>> tasks = await DBHelper.query();
taskList.assignAll(tasks.map((data) => new Task.fromJson(data)).toList());
}
Then I think you issue is your table is empty. After run your code try add something to your table then print it and see the result.

Error fetching API / A value of type 'List<Heroes>' can't be returned from the method 'getHeroes' because has a return type of 'Future<List<String>?>

im new in Dart/Flutter and im struggling with consuming API, here is my file thats inside my model folder:
List<Heroes> heroesFromJson(String str) =>
List<Heroes>.from(json.decode(str).map((x) => Heroes.fromJson(x)));
String heroesToJson(List<Heroes> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Heroes {
Heroes({
required this.id,
required this.name,
required this.localizedName,
required this.primaryAttr,
required this.attackType,
required this.roles,
});
int id;
String name;
String localizedName;
String primaryAttr;
String attackType;
List<String> roles;
factory Heroes.fromJson(Map<String, dynamic> json) => Heroes(
id: json["id"],
name: json["name"],
localizedName: json["localized_name"],
primaryAttr: json["primary_attr"],
attackType: json["attack_type"],
roles: List<String>.from(json["roles"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"localized_name": localizedName,
"primary_attr": primaryAttr,
"attack_type": attackType,
"roles": List<dynamic>.from(roles.map((x) => x)),
};
}
And here is where im getting the error, inside services folder:
class DotaServices {
Future<List<String>?> getHeroes() async {
var client = http.Client();
var url = Uri.parse('https://api.opendota.com/api/heroes');
var response = await client.get(url);
if (response.statusCode == 200) {
var json = response.body;
return heroesFromJson(json);
}
}
}
The error is occuring in that line:
return heroesFromJson(json);
And the message that appears is:
A value of type 'List<Heroes>' can't be returned from the method 'getHeroes' because it has a return type of 'Future<List<String>?>'.
how to solve it? Im struggling real hard on this :/
Your method returns a list of heroes... so... you need to return a list of heroes:
Future<List<String>?> getHeroes() async {
needs to be
Future<List<Heroes>?> getHeroes() async {
heroesFromJson returns a list of heroes so getHeroes has to return a list of heroes:
Future<List<Heroes>?> getHeroes()
Also, your method heroesFromJson returns a List<Heroes> not nullable, but your method getHeroes() return a List<Heroe>? which is nullable.
You either can make your return from heroesFromJson a nullable list List<T>? or your return from getHeroes() a non-nullable list List
Be careful making your List nullable or non-nullable List<Hero>?, not your Hero List<Hero?>
It seems to me that such code should work more reliably.
return Hero.fromJsonList(json as List);
This small example (including function main) was generated with a very small script.
import 'dart:convert';
import 'package:http/http.dart' as http;
void main(List<String> args) async {
final svc = DotaServices();
final heroes = await svc.getHeroes();
print('Heroes: ${heroes.length}');
}
class DotaServices {
Future<List<Hero>> getHeroes() async {
final client = http.Client();
final url = Uri.parse('https://api.opendota.com/api/heroes');
final response = await client.get(url);
if (response.statusCode == 200) {
final source = response.body;
final json = jsonDecode(source);
return Hero.fromJsonList(json as List);
}
throw StateError('Http error: ${response.statusCode}');
}
}
class Hero {
Hero(
{required this.id,
required this.name,
required this.localizedName,
required this.primaryAttr,
required this.attackType,
required this.roles});
factory Hero.fromJson(Map json) {
return Hero(
id: json['id'] as int,
name: json['name'] as String,
localizedName: json['localized_name'] as String,
primaryAttr: json['primary_attr'] as String,
attackType: json['attack_type'] as String,
roles: json['roles'] == null
? []
: (json['roles'] as List).map((e) => e as String).toList(),
);
}
final int id;
final String name;
final String localizedName;
final String primaryAttr;
final String attackType;
final List<String> roles;
static List<Hero> fromJsonList(List json) {
return json.map((e) => Hero.fromJson(e as Map)).toList();
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'localized_name': localizedName,
'primary_attr': primaryAttr,
'attack_type': attackType,
'roles': roles,
};
}
static List<Map<String, dynamic>> toJsonList(List<Hero> list) {
return list.map((e) => e.toJson()).toList();
}
}
Using this codegen script you can generate the models and serializers.
It also generates a working example.
import 'dart:io';
import 'package:object_serializer/json_serializer_generator.dart';
import 'package:yaml/yaml.dart';
void main() {
final classes = loadYaml(_classes) as Map;
final g = JsonSerializerGenerator();
final classesCode = g.generateClasses(classes);
final values = {
'classes': classesCode,
};
var source = g.render(_template, values);
source = g.format(source);
File('bin/stackoverflow.dart').writeAsStringSync(source);
}
const _classes = '''
Hero:
fields:
id: int
name: String
localizedName: {type: String, alias: localized_name}
primaryAttr: {type: String, alias: primary_attr}
attackType: {type: String, alias: attack_type}
roles: List<String>
''';
const _template = r'''
import 'dart:convert';
import 'package:http/http.dart' as http;
void main(List<String> args) async {
final svc = DotaServices();
final heroes = await svc.getHeroes();
print('Heroes: ${heroes.length}');
}
class DotaServices {
Future<List<Hero>> getHeroes() async {
final client = http.Client();
final url = Uri.parse('https://api.opendota.com/api/heroes');
final response = await client.get(url);
if (response.statusCode == 200) {
final source = response.body;
final json = jsonDecode(source);
return Hero.fromJsonList(json as List);
}
throw StateError('Http error: ${response.statusCode}');
}
}
{{classes}}
''';

Data gets lost when added to a Model

I am getting data from Firebase Database and Adding it to a List of my Model class. I tested the incoming data by printing to Console and it works fine, but once i add the data to my model class, it disappears.
Here's my Provider class where i'm loading the data.
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:local_stuffs_notification/apis/fcm.dart';
import 'package:local_stuffs_notification/models/request_model.dart';
import 'package:shared_preferences/shared_preferences.dart';
class IncomingRequest with ChangeNotifier {
List<RequestModel> _incomingRequests = [];
IncomingRequest(this._incomingRequests);
List<RequestModel> get incomingRequest {
return [..._incomingRequests];
}
Future<void> setIncomingRequest(RequestModel requestModel) async {
try {
DatabaseReference reference =
FirebaseDatabase.instance.ref("incomingRequests");
reference.child(requestModel.id).child(Fcm.getUid()).set(
{
"name": requestModel.name.toString(),
"phone": requestModel.phone.toString(),
"email": requestModel.email.toString(),
"fcmToken": requestModel.fcmToken.toString(),
},
);
notifyListeners();
} catch (error) {
rethrow;
}
}
Future<void> loadIncomingRequests() async {
try {
SharedPreferences preferences = await SharedPreferences.getInstance();
DatabaseReference reference = FirebaseDatabase.instance
.ref('incomingRequests/${preferences.getString('userId')!}');
Stream<DatabaseEvent> stream = reference.onValue;
stream.listen((DatabaseEvent event) {
print(event.snapshot.value);
final data = event.snapshot.value as Map;
print('data: $data');
final List<RequestModel> loadedRequest = [];
data.forEach(
(key, value) {
print('requestData: ${value['name']}');
loadedRequest.add(
RequestModel(
id: key.toString(),
name: value['name'].toString(),
fcmToken: value['fcmToken'].toString(),
phone: value['phone'].toString(),
email: value['email'].toString(),
),
);
print(loadedRequest);
},
);
_incomingRequests = loadedRequest;
print('LoadedRequests: $loadedRequest');
notifyListeners();
});
// reference.onValue.listen(
// (event) {
// if (event.snapshot.value == null) {
// return;
// }
// final data = event.snapshot.value as Map;
// final List<RequestModel> loadedRequests = [];
// data.forEach(
// (key, requestData) {
// loadedRequests.add(
// RequestModel(
// id: key,
// name: requestData['name'],
// fcmToken: requestData['fcmToken'],
// phone: requestData['phone'],
// email: requestData['email'],
// ),
// );
// },
// );
// _incomingRequests = loadedRequests;
// notifyListeners();
// },
//);
} catch (error) {
rethrow;
}
}
}
Here's my Model Class
class RequestModel {
final String id;
final String name;
final String fcmToken;
final String phone;
final String email;
RequestModel({
required this.id,
required this.name,
required this.fcmToken,
required this.phone,
required this.email,
});
}
I'm getting the data until i added it to loadedRequest List
Please help, i've spent hours on this and i don't know what i'm doing wrong. When i print the loadedRequest list, i get an empty list. Thanks.
Those logs aren't showing an empty list - It says [Instance of 'RequestModel']. That means there is a value there, but Dart simply doesn't know how to convert RequestModel to a String so that it can be printed out on the console.
An empty list would be printed simply as [], and if you had two values, for example, you would see [Instance of 'RequestModel', Instance of 'RequestModel'].
To print out your values with more detail, you can override the toString() method on your class.
For example:
class RequestModel {
final String id;
final String name;
final String fcmToken;
final String phone;
final String email;
RequestModel({
required this.id,
required this.name,
required this.fcmToken,
required this.phone,
required this.email,
});
#override
String toString() =>
"RequestModel(id: $id, name: $name, fcmToken: $fcmToken, phone: $phone, email: $email)";
}
take a look at the raw data once again, it contains all the users data so you need to get the access the uid before the name
final uid = FirebaseAuth.instance.currentUser!.uid;
and then for the RequestModel:
name: data[uid]['name']

List from Model class is not storing in the new list in the controller class

**Product Modelclass which extracted from json file**
class Product {
int? _totalSize;
int? _typeId;
int? _offset;
late List<ProductModel> _products;
List<ProductModel> get products=> _products;
Product({required totalSize, required typeId, required offset, required products}){
this. _totalSize=totalSize;
this. _typeId=typeId;
this. _offset=offset;
this. _products=products;
}
Product.fromJson(Map<String, dynamic> json) {
_totalSize = json['total_size'];
_typeId = json['type_id'];
_offset = json['offset'];
if (json['productModel'] != null) {
_products= <ProductModel>[];
json['products'].forEach((v) {
_products.add(new ProductModel.fromJson(v));
});
}
}
}
class ProductModel {
int? id;
String? name;
String? description;
int? price;
int? stars;
String? img;
String? location;
String? createdAt;
String? updatedAt;
int? typeId;
ProductModel(
{this.id,
this.name,
this.description,
this.price,
this.stars,
this.img,
this.location,
this.createdAt,
this.updatedAt,
this.typeId});
ProductModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
description = json['description'];
price = json['price'];
stars = json['stars'];
img = json['img'];
location = json['location'];
createdAt = json['created_at'];
updatedAt = json['updated_at'];
typeId = json['type_id'];
}
}
This is my Api_client class extending Getx to get response from server
import 'package:get/get.dart';
class Api_client extends GetConnect{
late String token;
late String AppbaseUrl;
late Map<String,String> _mainHeader;
Api_client({required this.AppbaseUrl}){
baseUrl=AppbaseUrl;
timeout=Duration(seconds: 30);
token="";
_mainHeader={
'Content-type':' application/json; charset-UTF-8',
'Authorization':' Bearer $token',
};
}
Future <Response> getData(String uri) async{
try{
Response response = await get(uri);
return response;
}catch(e){
return Response(statusCode: 1,statusText: e.toString());
}
}
}
**This is Popular_Product_List_Repo class extending Getx
getservices to get response from Api_client**
import 'package:get/get.dart';
import 'package:untitled/data/api/Api_client.dart';
class Popular_Product_List_Repo extends GetxService{
final Api_client apiClient;
Popular_Product_List_Repo({ required this.apiClient});
Future <Response> get_popular_product_list()async{
return await
apiClient.getData("/api/v1/products/popular");
}
}
This is my controller class Popular_Product_Controller which is responsible for to get response from Popular_Product_List_Repo and retrieve the list and store the list in my new created List which is List_Popular_product_list=[]; to show the list on my UI
import 'package:get/get.dart';
import 'package:untitled/data/Repository/Popular_Product_List_Repo.dart';
import 'package:untitled/data/models/Products_model.dart';
class Popular_Product_Controller extends GetxController{
final Popular_Product_List_Repo popular_product_repo ;
List<dynamic>_Popular_product_list=[];
Popular_Product_Controller({required this.popular_product_repo});
Future getPopular_Product_list() async{
Response response=await popular_product_repo.get_popular_product_list();
if(response.statusCode==200){
print("got products");
_Popular_product_list=[];
_Popular_product_list.addAll(Product.fromJson(response.body).products);
print(_Popular_product_list);
update();
}else{
}
}
}
Problem is I want to make sure that response from server is right and stored without any issue in my list _Popular_product_list which I created in the Popular_Product_Controller I wrote print statement which is got products and _Popular_product_list itself to check that data is inside the _Popular_product_list or not so whenever I run its not showing either any statements which means the function getPopular_Product_list() is not working as I expected so what is went wrong and why list products is not storing inside the _Popular_product_list ?
In order to verify if you are getting some data.. you can use the **Either** class in Dart which can imported from pub.dev. its make it easy to handle
for example,
final Either<String, List<Product>> result =
await getProductList();
result.fold((exception) {
CustomToast.showErrorToast(Messages.UNABLE_TO_LOAD_PRODUCT_LIST);
}, (products) async {
//get products here and you can do what you want
}

How to extract data from a multipart/form-data response?

I am uploading images to a storageAPI using POST method with content-type of multipart/form-data. The api returns an object response that looks as below:
{
"id": "6d50c066-cf65-4748-8b9a-183c3526f49b",
"name": "hotel_6.jpg",
"fileKey": "lv/im/5d9feb8e-2ea8-439d-a550-1e937081e085-hotel_6.jpg",
"fileExtension": ".jpg",
"mimeType": "image/jpeg",
"catalogueUrl": {
"mainUrl": "https://xy.abc.com/lv/im/5d9feb8e-2ea8-439d-a550-1e937081e085-hotel_6.jpg",
"thumbnailUrls": []
},
"createdAt": "2021-11-25T06:40:40.0869466+00:00"
}
How can I extract the variable "mainUrl" from the response so that I can assign its value to the _pictureController? Here is what I have done:
uploadFile() async {
var accessToken = await sharedPref.read(key);
var postUrl = '$baseUrl/catalogue?thumbnail=${param.thumbnailTrueFalse}';
Map < String, String > headers = {
"Authorization": "Bearer $accessToken",
};
// multipart request object
var request = http.MultipartRequest("POST", Uri.parse(postUrl));
request.headers.addAll(headers);
// add selected file with request
request.files.add(http.MultipartFile("file", imageStream, imageSize,
filename: imageName));
// Send request
var response = await request.send();
// Read response
var result = await response.stream.bytesToString();
print('readResponse: $result');
if (response.statusCode == 200) {
var data = StorageResponse.fromJson(jsonDecode(result));
print('data: $data');
setState(() {
_pictureController.text = data.catalogueUrl!.mainUrl!;
});
return data;
} else {
throw Exception('Failed to upload photo.');
}
}
The "StorageResponse" Class is as follows:
#JsonSerializable()
class StorageResponse {
var id;
var name;
var fileKey;
var fileExtension;
var mimeType;
Catalogue ? catalogueUrl;
var createdAt;
StorageResponse({
this.id,
this.name,
this.fileKey,
this.fileExtension,
this.mimeType,
this.catalogueUrl,
this.createdAt,
});
factory StorageResponse.fromJson(Map < String, dynamic > json) =>
_$StorageResponseFromJson(json);
Map < String, dynamic > toJson() => _$StorageResponseToJson(this);
#override
toString() {
String output =
'{id:${this.id},name:${this.name},fileKey: ${this.fileKey},fileExtension:${this.fileExtension},mimeType: ${this.mimeType}mimeType},catalogueUrl: ${this.catalogueUrl},,createdAt: ${this.createdAt}}';
return output;
}
}
You can use the following structure to convert a Json file to a class, and vice versa.
The following structure works properly.
import 'dart:convert';
class StorageResponse {
final String id;
final String name;
final String fileKey;
final String fileExtension;
final String mimeType;
Catalogue catalogueUrl;
final DateTime createdAt;
StorageResponse(
this.id,
this.name,
this.fileKey,
this.fileExtension,
this.mimeType,
this.catalogueUrl,
this.createdAt,
);
factory StorageResponse.fromMap(Map<String, dynamic> json) {
return StorageResponse(
json['id'],
json['name'],
json['fileKey'],
json['fileExtension'],
json['mimeType'],
Catalogue.fromMap(json['Catalogue']),
DateTime.parse(json['createdAt']));
}
Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'fileKey': fileKey,
'fileExtension': fileExtension,
'mimeType': mimeType,
'Catalogue': catalogueUrl.toJson(),
'createdAt': createdAt
};
#override
toString() {
String output =
'{id:${this.id},name:${this.name},fileKey: ${this.fileKey},fileExtension:${this.fileExtension},mimeType: ${this.mimeType}mimeType},catalogueUrl: ${this.catalogueUrl},,createdAt: ${this.createdAt}}';
return output;
}
}
class Catalogue {
final String mainUrl;
final List<String> thumbnailUrls;
Catalogue(this.mainUrl, this.thumbnailUrls);
factory Catalogue.fromMap(Map<String, dynamic> json) {
return Catalogue(json['mainUrl'], jsonDecode(json['thumbnailUrls']));
}
Map<String, dynamic> toJson() =>
{'mainUrl': mainUrl, 'thumbnailUrls': jsonEncode(thumbnailUrls)};
}
for use
if (response.statusCode == 200) {
var data = StorageResponse.fromMap(jsonDecode(result));
print('data: $data');
setState(() {
_pictureController.text = data.catalogueUrl!.mainUrl!;
});
return data;
} else {
throw Exception('Failed to upload photo.');
}