Storing API data into SQLite - sql

I want to fetch data from a REST API and store the information in my local database but get errors like :
_TypeError (type '(Map<String, dynamic>) => QuizDescription' is not a subtype of type '(dynamic) => QuizDescription' of 'f')
My List model:
factory QuizDescription.fromJson(Map<String, dynamic> json) =>
QuizDescription(
quizID: json['id'],
quizname: json['quizname'],
kurzbeschreibung: json['kurzbeschreibung'],
beschreibung: json['beschreibung'],
preis: json['preis'],
quizbild: json['quizbild']['url'],
rating: json['_rating_of_quiz']['rating_rating'],
);
Map<String, dynamic> toJson() => {
"quizID": quizID,
"quizname": quizname,
"kurzbeschreibung": kurzbeschreibung,
"beschreibung": beschreibung,
"preis": preis,
"quizbild": quizbild,
"rating": rating,
};
Database-Create method where I want to store information in :
static Future<int> createQuiz(QuizDescription quiz) async {
Database db = await DBQUIZProvider.initQuizDB();
return await db.insert('quiz', quiz.toJson());
}
API Call - which is using the Database method:
var url = Uri.parse('${Constants.BASE_URL}/QUIZ/getall');
var headers = {'Content-Type': 'application/json'};
var res = await http.get(
url,
headers: headers,
);
final body = json.decode(res.body);
QuizDescription quizliste =
body.map<QuizDescription>(QuizDescription.fromJson).toList();
DBQUIZProvider.createQuiz(quizliste);

try this...
var url = Uri.parse('${Constants.BASE_URL}/QUIZ/getall');
var headers = {'Content-Type': 'application/json'};
var res = await http.get(url, headers: headers,);
List tempList = json.decode(res.body);
Database-Create method where store information in
static Future<int> createQuiz(List quiz) async {
int result = 0;
Database db = await DBQUIZProvider.initQuizDB();
for (var element in planets) {
QuizDescription quizD = QuizDescription. fromJson(element);
result = await db.insert(
'quiz',
quizD.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
return result;
}

try this:
static Future<int> createQuiz(Map<String, dynamic> row) async {
Database db = await DBQUIZProvider.initQuizDB();
return await db.insert('quiz', row);
}

Related

Flutter : unhandled exception: invalid argument

I'm trying to send two list of images file and i have an error with that and i don't know why this happen
this is the function which i use for that :
Future<dynamic> upload(List<File> imageFile, List<File> backID) async {
var headers =
Provider.of<LoginUserProvider>(context, listen: false).httpHeader;
var uri = Uri.parse(
"xyz");
var request = new http.MultipartRequest("POST", uri);
var requestCopy = new http.MultipartRequest("POST", uri);
request.headers.addAll(headers);
//request.headers.addAll(Environment.requestHeaderMedia);
for (int i = 0; i < uploadedFilesList.length; i++) {
var length = await imageFile[i].length();
var stream =
// ignore: deprecated_member_use
new http.ByteStream(DelegatingStream.typed(imageFile[i].openRead()));
var multipartFile = http.MultipartFile(
'back_id_photos[$i]',
stream,
length,
contentType: MediaType('application', 'x-tar'),
);
var multipartFilePhotos = new http.MultipartFile(
'photos[$i]',
stream,
length,
contentType: MediaType('application', 'x-tar'),
);
request.fields['section_id'] = VillaID.toString();
request.fields['start_date'] = requeststartDate;
request.fields['end_date'] = requestendDate;
request.fields['names'] = _nameController.toString();
request.fields['phones'] = _phoneController.toString();
request.fields['photos'] = multipartFilePhotos.toString();
request.fields['back_id_photos'] = multipartFile.toString();
//contentType: new MediaType('image', 'png'));
request.files.add(multipartFile);
request.files.add(multipartFilePhotos);
var response = await request.send();
print(response.statusCode);
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
var streamedResponse = await requestCopy.send();
var responses = await http.Response.fromStream(streamedResponse);
// ignore: unused_local_variable
final responseData = json.decode(responses.body) as Map<String, dynamic>;
print(json.decode(responses.body));
if (response.statusCode == 200 || response.statusCode == 201) {
return true;
}
}
}
and in the part of
var response = await request.send();
I have the error exactly before the dot (.) and this is the error which shown
unhandled exception: invalid argument(s) (input): must not be null
Can anyone tell me what should i do to solve that !
Send your Multipart Part Files as below and Use await http.Multipart as accessing file is async function and need a promise to run.
Try this:
await http.MultipartFile(
'back_id_photos[$i]',
stream,
length,
contentType: MediaType('application', 'x-tar'),
);
OR
request.files.add(new http.MultipartFile.fromBytes('file', await File.fromUri("<path/to/file>").readAsBytes(), contentType: new MediaType('image', 'jpeg')))
Follow this link

Class mapping using dart

I have this class(dart)
class ResumenPublicaciones {
String name;
String count;
ResumenPublicaciones({this.name, this.count});
// named constructor
ResumenPublicaciones.fromJson(Map<String, dynamic> json)
: name = json['name'],
count = json['count'].toString();
}
I want to map this response from the API
[{"name":"Administración","count":37},{"name":"Call Center,
Teletrabajo y Telemarketing","count":4},{"name":"Compras,
Importaciones, Logística, Distribución","count":10}]
this is how Im doing it....
class ServicioResumenEmpleos {
List<ResumenPublicaciones> publicaciones = [];
List getResumenPublicacioness() {
publicacionesResumidas();
return publicaciones;
}
var apiUrl = "here my api URLs";
Future<ResumenPublicaciones> publicacionesResumidas() async {
var jsonResponse;
Map<String, String> headers = {
'Content-Type': 'application/json',
};
var response = await http.get(apiUrl, headers: headers);
print('respuesta del api' + response.toString());
if (response.statusCode == 200) {
print(' el API responde ' + response.body);
jsonResponse = json.decode(response.body);
var _listapublicaciones = new ResumenPublicaciones.fromJson(jsonResponse);
publicaciones.add(_listapublicaciones);
print(_listapublicaciones.name);
return _listapublicaciones;
} else {
print(
'Esta imprimiendo el else en este punto no debe impremir el response');
var _listapublicacionesNull = new ResumenPublicaciones();
_listapublicacionesNull.count = '0';
_listapublicacionesNull.name = 'didnt work';
return _listapublicacionesNull;
}
}
//
}
I want to receive a list on the class but im receiving this error msg
Exception has occurred.
**_TypeError (type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>')**
any Idea of what im doing wrong?
The problem is here:
var _listapublicaciones = new ResumenPublicaciones.fromJson(jsonResponse);
If your response is a list, you are passing it to a constructor that is expecting a Map. You need to iterate over the objects of your list and convert them into individual publicaciones:
var _listapublicaciones = (jsonResponse as List).map(
(o) => ResumenPublicaciones.fromJson(o),
).toList();

Future method calling api sometimes returns null sometimes not

In this method, the output is as follows:
I/flutter ( 2928): 200
I/flutter ( 2928): null
I/flutter ( 2928): [Instance of 'Images']
This is causing snapshot.data to be null in my FutureBuilder as well.Any Idea why is this happening?
Future<List<Images>> getData( File f ) async {
List<Images> list;
// String link = "https://clothest.herokuapp.com/";
String link ="https://us-central1-velvety-rookery-274308.cloudfunctions.net/function-1";
var stream = new http.ByteStream(DelegatingStream.typed(f.openRead()));
var length = await f.length();
var postUri = Uri.parse(link);
var request = new http.MultipartRequest("POST", postUri);
var multipartFileSign = new http.MultipartFile('File', stream, length,
filename: basename(f.path));
request.files.add(multipartFileSign);
request.headers.addAll({"content-type": "application/json"});
var response = await request.send();
print(response.statusCode); //200 OK
if (response.statusCode == 200){
response.stream.transform(utf8.decoder).listen((value) {
var data = json.decode(value);
var rest = data["Items"] as List;
list = rest.map<Images>((json) => Images.fromJson(json)).toList();
print(list.toString());
});
}
print(list.toString());
return list;
}
So I managed to solve this problem by using another package instead of the HTTP package. Dios package is the best regarding HTTP requests. Updated code:
Future<List<Images>> getData( File f ) async {
List<Images> lst=[];
String link ="https://us-central1-velvety-rookery-274308.cloudfunctions.net/function-1";
Dio dio = new Dio();
FormData formdata = new FormData(); // just like JS
formdata.add('File', new UploadFileInfo(f, basename(f.path)));
await dio.post(link, data: formdata, options: Options(
method: 'POST',
responseType: ResponseType.JSON // or ResponseType.JSON
)).then((response) {
print(response);
if(response.statusCode==200){ //OK
var responseBody = response.data; //Map
var rest = responseBody["Items"] as List;
//print(rest);
lst = rest.map<Images>((json) => Images.fromJson(json)).toList(); //instances of 'Images' object
//print(lst);
}
}
).catchError((error) => print(error));
return lst;

Calling multiple APIs slows down the app to load?

So I have made a News App using APIs available on the internet. So I had to use different API for each different Category. There are more than 9 categories, So this is making my app load very slow. So, what is the solution to this. How can I only call 2 APIs at the initial state and rest of the others after some time when the app has loaded.
See the code below:
class NewsCard extends StatefulWidget {
#override
_NewsCardState createState() => _NewsCardState();
}
class _NewsCardState extends State<NewsCard>
with SingleTickerProviderStateMixin {
TabController tabController;
static DateTime now = DateTime.now();
String formattedDate;
List newsData;
List topNews1;
List businessNews1;
List worldNews1;
List sportsNews1;
List entertainmentNews1;
List educationNews1;
List tvnews1;
List electionNews1;
List lifeNews1;
bool isLoading = true;
final String toi= "https://timesofindia.indiatimes.com/";
final String topNews =
"API url";
final String sportsNews =
"API url";
final String businessNews =
"API url";
final String worldNews =
"API url ";
final String entertainmentNews =
"API url ";
final String educationNews =
"API url";
final String tvNews =
"API url ";
final String electionNews =
"API url";
final String lifeNews =
"API url";
final String url =
"https://newsapi.org/v2/top-headlines?sources=google-news-in&apiKey=";
Future getData() async {
var response = await http.get(
Uri.encodeFull(url),
headers: {
HttpHeaders.authorizationHeader: ""
},
);
var response1 = await http.get(
Uri.encodeFull(topNews),
);
var response2 = await http.get(
Uri.encodeFull(businessNews),
);
var response3 = await http.get(
Uri.encodeFull(worldNews),
);
var response4 = await http.get(
Uri.encodeFull(sportsNews),
);
var response5 = await http.get(
Uri.encodeFull(entertainmentNews),
);
var response6 = await http.get(
Uri.encodeFull(tvNews),
);
var response7 = await http.get(
Uri.encodeFull(lifeNews),
);
var response8 = await http.get(
Uri.encodeFull(electionNews),
);
var response9 = await http.get(
Uri.encodeFull(educationNews),
);
List data = jsonDecode(response.body)['articles'];
List topNewsData = jsonDecode(response1.body)['stories'];
List businessNewsData = jsonDecode(response2.body)['items'][0]['stories'];
List worldNewsData = jsonDecode(response3.body)['items'][0]['stories'];
List sportsNewsData = jsonDecode(response4.body)['items'][0]['stories'];
List entertainmentNewsData = jsonDecode(response5.body)['items'][0]['stories'];
List tvNewsData = jsonDecode(response6.body)['items'][0]['stories'];
List lifeNewsData = jsonDecode(response7.body)['items'][0]['stories'];
List electionsNewsData = jsonDecode(response8.body)['items'][0]['stories'];
List educationNewsData = jsonDecode(response9.body)['items'][0]['stories'];
setState(() {
newsData = data;
topNews1 = topNewsData;
businessNews1 = businessNewsData;
worldNews1 = worldNewsData;
sportsNews1 = sportsNewsData;
entertainmentNews1 = entertainmentNewsData;
tvnews1 = tvNewsData;
lifeNews1=lifeNewsData;
electionNews1 = electionsNewsData;
educationNews1 = educationNewsData;
isLoading = false; //this is for the initial loading, this is taking too much of time.
});
}
#override
void initState() {
super.initState();
this.getData();
tabController = TabController(vsync: this, length: 9);
}
Inside the Scaffold
isLoading
?Column(....):Column(.....)
Do keep in Mind that i am a beginner in Flutter, So if my method of approach is wrong then kindly request me to do the perfect approach.
Since there is no dependency between different api calls (api call 1 need not wait for api call 0 to finish), better to start them all and await for the results at end. So don't use await for every api call. Instead use Future.wait to wait for all futures at the end. Something like:
Future getData() async {
List<Future> responseFutures = [
http.get(
Uri.encodeFull(url),
headers: {HttpHeaders.authorizationHeader: ""},
),
http.get(
Uri.encodeFull(topNews),
),
http.get(
Uri.encodeFull(businessNews),
),
http.get(
Uri.encodeFull(worldNews),
),
http.get(
Uri.encodeFull(sportsNews),
),
http.get(
Uri.encodeFull(entertainmentNews),
),
http.get(
Uri.encodeFull(tvNews),
),
http.get(
Uri.encodeFull(lifeNews),
),
http.get(
Uri.encodeFull(electionNews),
),
http.get(
Uri.encodeFull(educationNews),
),
];
List responses = await Future.wait(responseFutures);
List data = jsonDecode(responses[0].body)['articles'];
List topNewsData = jsonDecode(responses[1].body)['stories'];
List businessNewsData = jsonDecode(responses[2].body)['items'][0]['stories'];
List worldNewsData = jsonDecode(responses[3].body)['items'][0]['stories'];
List sportsNewsData = jsonDecode(responses[4].body)['items'][0]['stories'];
List entertainmentNewsData = jsonDecode(responses[5].body)['items'][0]['stories'];
List tvNewsData = jsonDecode(responses[6].body)['items'][0]['stories'];
List lifeNewsData = jsonDecode(responses[7].body)['items'][0]['stories'];
List electionsNewsData = jsonDecode(responses[8].body)['items'][0]['stories'];
List educationNewsData = jsonDecode(responses[9].body)['items'][0]['stories'];
setState(() {
newsData = data;
topNews1 = topNewsData;
businessNews1 = businessNewsData;
worldNews1 = worldNewsData;
sportsNews1 = sportsNewsData;
entertainmentNews1 = entertainmentNewsData;
tvnews1 = tvNewsData;
lifeNews1 = lifeNewsData;
electionNews1 = electionsNewsData;
educationNews1 = educationNewsData;
isLoading = false; //this is for the initial loading, this is taking too much of time.
});
}

flutter: is it best practice code to fetch list of posts?

My Flutter Code to fetch posts from API is:
Future<List<Posts>> fetchPosts() async {
var url = 'https://*****.com/wp-json/wp/v2/posts';
final response = await http.get(url, headers: {"Accept": 'application/json'});
if (response.statusCode == 200) {
setState(() {
var jsonData = json.decode(response.body);
for (var p in jsonData) {
Posts post = Posts(
id: p['id'],
date: p['date'],
title: p['title'],
link: p['link'],
postViews: p['views'],
featuredImage: p['featured_image'],
featuredImageBig: p['featured_image_big'],
categories: p['categories'],
comments: p['comments'],
content: p['content'],
);
posts.add(post);
}
});
}
}}
I ask is it best practice code to fetch list of posts ?
thanks advance
Let's assume that you have a Class called Post:
class Post {
final String id;
final String link;
final String imageUrl;
final String title;
Post(this.id, this.link, this.imageUrl, this.title);
factory Post.fromJson(Map<String, dynamic> json) {
return new Post(json['id'], json['link'], json['imageUrl'], json['title']);
}
static Future<List<Post>> get(int skip, int take) async {
var response =
await Api.get('api/v1/posts?SkipCount=$skip&MaxResultCount=$take&');
final responseJson = json.decode(response.body);
final items = (responseJson["items"] as List).map((i) => new Post.fromJson(i));
return items.toList();
}
}
The only other thing you need it the Api class:
import 'dart:async';
import 'package:http/http.dart' as http;
class Api{
static const String BaseUrl = 'http://yourapiwebsite.com/';
static Future<http.Response> get(String url){
return http.get(BaseUrl + url);
}
}
This can handle all of your normal calls. If you are intending to pass dynamic parameters from UI to the API, you can have a bloc and get the parameter from it.
First of all, i think you don't return anything in your function. Also the variable posts, which i guess is a List doesn't exist inside of your function. So I would change it like this:
Future<List<Posts>> fetchPosts() async {
List<Posts> posts = [];
var url = 'https://*****.com/wp-json/wp/v2/posts';
final response = await http.get(url, headers: {"Accept": 'application/json'});
if (response.statusCode == 200) {
setState(() {
var jsonData = json.decode(response.body);
for (var p in jsonData) {
Posts post = Posts(
id: p['id'],
date: p['date'],
title: p['title'],
link: p['link'],
postViews: p['views'],
featuredImage: p['featured_image'],
featuredImageBig: p['featured_image_big'],
categories: p['categories'],
comments: p['comments'],
content: p['content'],
);
posts.add(post);
}
});
}
return posts;
}}
This implementation is good for a small scale application. When the scale of your application increases, and you might support different kind of requests and such kind, you should take a look at the Bloc pattern for best practice.
You can find an example of using the Bloc pattern together with a web API on the channel of Tensor Programming: https://www.youtube.com/watch?v=ALcbTxz3bUw