A value of type can't be returned from method because it has a return type of - flutter

List<String> getData() async {
var response = await http.get(url);
if (response.statusCode == 200) {
String data = response.body;
print(data);
var temperature = jsonDecode(data)['main']['temp'];
var condition = jsonDecode(data)['weather'][0]['id'];
var city_name = jsonDecode(data)['name'];
return [temperature, condition, city_name];
} else {
print(response.statusCode);
}
}
}
I get a strange error saying that I can't return List<String> because is expecting List<String> to be returned.

Since the function get data is is async it should return Future<List<String>> example is as follows:
Future<List<String>> getData() async {
var response = await http.get(url);
if (response.statusCode == 200) {
String data = response.body;
print(data);
var temperature = jsonDecode(data)['main']['temp'];
var condition = jsonDecode(data)['weather'][0]['id'];
var city_name = jsonDecode(data)['name'];
return <String>[temperature, condition, city_name];
} else {
print(response.statusCode);
}
}
Also your are decoding 3 times unnecessarily, you can do it once keep it in var and use for further usage, example as follows:
String data = response.body;
var decodedData = jsonDecode(data);
var temperature = decodedData['main']['temp'];
var condition = decodedData['weather'][0]['id'];
var city_name = decodedData['name'];

As a generalization, when you get this error in an async function:
A value of type x can't be returned from method because it has a
return type of x
The message seems weird, but it could mean that you are missing a Future<> return type.
So add Future<> to your method return type:
Example:
List<String> getValues() async
{
List<String> list = await getJson();
return list;
}
Change to:
Future<List<String>> getValues() async
{
List<String> list = await getJson();
return list;
}

Related

Replace "map" method to traditional loops in dart when fetching data from API

I was wondering if there is a different approach more efficient to include data from a json API to a simple list.
As I read in some posts, map method is the most time/resource consuming in comparation with the traditional for/while loop in Dart.
Currently I use this snippet to fetch my data:
Future<List<dynamic>> fetchData(url) async {
var client = http.Client();
final response = await client.get(Uri.parse(url));
await Future.delayed(Duration(seconds:2));
if (response.statusCode == 200) {
var jsonDecoded = json.decode(response.body);
BreedList = jsonDecoded.map((data) => DogClass.fromJson(data)).toList();
glossarList = BreedList;
return BreedList;
} else {
throw Exception('Failed to load data');
}
}
I tried this approach:
Future<List<dynamic>> fetchDataFor(url) async {
var client = http.Client();
final response = await client.get(Uri.parse(url));
await Future.delayed(Duration(seconds:2));
if (response.statusCode == 200) {
var jsonDecoded = json.decode(response.body);
for (var k in jsonDecoded.keys){
BreedList.add({jsonDecoded[k]});
}
return BreedList;
} else {
throw Exception('Failed to load data');
}
}
But it returns the error: Class List has no instance getter 'keys'.
So, what would be the equivalent for the "map" method ?
You can use collection-for to perform a straightforward transformation of .map calls.
var result = iterable.map((element) => transform(element)).toList();
can be replaced with:
var result = [for (var element in iterable) transform(element)];
So in your case:
BreedList = jsonDecoded.map((data) => DogClass.fromJson(data)).toList();
can become:
BreedList = [for (var data in jsonDecoded) DogClass.fromJson(data)];

hive condition if id exist

i use this code putData but it shown repeat, i want to show my data from database to hive.box,i just want: if there is same id or exist, it cannot store to hive.box database.if not same or exist it wil store to databse hive.box.
this is getdata from mysql database
Future getAllData() async {
await openBox();
String url = "http://dhoido.com/sttt/tes/viewHive.php";
try{
var response = await http.get(Uri.parse(url));
var _jsonDecode = jsonDecode(response.body);
// setState(() {
// var resBody = json.decode(response.body);
// list = resBody;
// });
// box.clear();
// if (box.get('id').exists ) {
await putData(_jsonDecode) as List;
// }
} catch (SocketException) {
print(SocketException);
}
Future putData(data) async {
for(var d in data) {
d = TodoModel(
id: d['id'],
title: d['title'],
detail: d['detail'],
isCompleted: false
);
if(d != box.values.toList()){
box.add(d);
}
else{
box.clear();
}
}

How to mix 2 json response to 1 list in Flutter

How to mix 2 json response to 1 list in flutter?
I have 2 json https://api.thecatapi.com/v1/images/search?limit=10&page=1&order=Desc and https://catfact.ninja/facts?limit=10.
Need create 1 model list with ['catimageurl'] from first and ['catfact'] from second .
I try this code but catqfact return null
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:async';
class CatsModel {
final String caturl;
final String catqfact;
CatsModel({this.caturl, this.catqfact});
factory CatsModel.fromJson(Map<String, dynamic> jsonData) {
return CatsModel(caturl: jsonData['url'], catqfact: jsonData['fact']);
}
}
Future<List<CatsModel>> getCat() async {
var url = Uri.parse(
'https://api.thecatapi.com/v1/images/search?limit=10&page=1&order=Desc');
var response = await http.get(url);
if (response.statusCode == 200) {
List cats = json.decode(response.body);
return cats.map((cat) => CatsModel.fromJson(cat)).toList();
} else
throw Exception('Json data download error');
}
Future<List<CatsModel>> getCatFact() async {
var url = Uri.parse('https://catfact.ninja/facts?limit=10');
var response = await http.get(url);
if (response.statusCode == 200) {
List catsFacts = json.decode(response.body);
return catsFacts.map((cat) => CatsModel.fromJson(cat)).toList();
} else
throw Exception('Json data download error');
}
you just need one function, since you have to combine data anyway.
Future<List<CatsModel>> getCatData() async {
var imagesUri = Uri.parse('https://api.thecatapi.com/v1/images/search?limit=10&page=1&order=Desc');
var factsUri = Uri.parse('https://catfact.ninja/facts?limit=10');
var imagesResponse = await http.get(imagesUri);
var factsResponse = await http.get(factsUri);
if (imagesResponse.statusCode == 200 && factsResponse.statusCode == 200) {
List images = json.decode(imagesResponse.body);
List facts = json.decode(factsResponse.body)['data'];
List<CatsModel> cats = [];
for (int i = 0; i < images.length; i++) {
cats.add(CatsModel(caturl: images[i]['url'], catqfact: facts[i]['fact']));
}
return cats;
} else
throw Exception('Json data download error');
}
Here is the pastebin link for the full working code
This is what it looks like.
Comment, if you feel you have doubt about any part. I'll explain.

Flutter : How to add more json data to existing Model Class?

I have a scenario where the following function is called again and again whenever the user hits the "Load More" button.
The problem I'm facing is, that it replaces previously loaded data with a new one. Instead, it should add to the bottom of the Listview.Builder
Future fetchData() async{
var url = "url_goes_here";
final response = await http.get(url);
if (response.statusCode == 200) {
var resBody = jsonDecode(response.body);
var data = resBody['data'] as List;
if (data.isNotEmpty) {
setState(() {
listVariable = data
.map<ModelClass>((json) => ModelClass.fromJson(json))
.toList();
});
}
}
}
List<ModelClass> listVariable =List<ModelClass>(); //describe the object that way.
--------and---------
data.map<ModelClass>((json) {
listVariable.add(ModelClass.fromJson(jsonn));
} )).toList();
You should add received data to your listVariable, not assign a new value. Try this code:
final listVariable = <ModelClass>[];
...
Future fetchData() async {
var url = "url_goes_here";
final response = await http.get(url);
if (response.statusCode == 200) {
var resBody = jsonDecode(response.body);
var data = resBody['data'] as List;
if (data.isNotEmpty) {
final list = data.map<ModelClass>((json) => ModelClass.fromJson(json));
setState(() {
listVariable.addAll(list); // HERE: addAll() instead of assignment
});
}
}
}
I was able to figure out answer myself.
setState(() {
listVariable.addAll(data
.map<ModelClass>((json) => ModelClass.fromJson(json))
.toList();
}));
#Mol0ko and #hasan karaman both are right but #Mol0ko
Makes better sense when you have a set of data to addAll to existing data.

Getting this error - type 'Future<dynamic>' is not a subtype of type 'List<dynamic>'

Whenever trying to call future data and trying converting to List, it returns the error
type 'Future' is not a subtype of type 'List'
Tried type-casting, but no help
On HomePage.dart
final getPost = NetworkFile().getPosts();
List posts;
void getPostsList() {
setState(() {
var res = getPost;
posts = res as List<dynamic>;
print(posts);
});
}
On Network.dart
class NetworkFile{
Future<dynamic> getPosts() async {
var response = await http.get('$kBlogURL' + 'posts?_embed');
Iterable resBody = await jsonDecode(response.body.toString());
return resBody;
}
}
You are decoding the response and its a List of type dynamic. There are few method to handle it. You can create a simple PODO class and cast/mapped to it. Or just do like below:
List posts = [];
void getPostsList() async {
final fetchedPosts = await NetworkFile().getPosts();
setState(() {
posts = fetchedPosts;
});
print(posts);
}
Here is a nice article about PODO.
final getPost = NetworkFile().getPosts();
Map posts;
void getPostsList() async {
var res = await getPost;
setState(() {
posts = res as Map<String, dynamic>;
print(posts);
});
}
class NetworkFile {
Future<dynamic> getPosts() async {
var response = await http.get('https://onetechstop.net/wp-json/wp/v2');
var resBody = await jsonDecode(response.body.toString());
return resBody;
}
}