I already have a button to fetch the API with function to ++increment index and set the new parameter on every click. My question is, how to set 'like a cache' for json response as index?
here my http.post request =
List<dynamic> _myResponse = [];
Future<void> trytoFetch(myIndex, parameter) async {
var url =
"https://jsonplaceholder.typicode.com/posts/$parameter";
Map<String, String> headers = {
'Content-type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(url, headers: headers);
final responseJson = json.decode(response.body);
if (response.statusCode == 200) {
setState(() {
_myResponse[myIndex] = responseJson; // ITS DOESNT WORKS
});
} else {
setState(() {});
throw Exception('Failed to load internet');
}
}
My goal is like
if (response.statusCode == 200) {
setState(() {
_myResponse[0] = responseJson; // return responseJson from parameter
// Then I click the button with new parameter value and increment index
_myResponse[1] = responseJson; // return responseJson from new parameter
// Then I click the button with another new parameter value and increment index
_myResponse[2] = responseJson; // return responseJson from new parameter again
});
} else {
setState(() {});
throw Exception('Failed to load internet');
}
and in the end, I can simply print the returned json
print(_myResponse[0]);
print(_myResponse[1]);
print(_myResponse[2]);
How to achieve this? is it possible? Thanks
First of, you shouldn't pass index as a parameter to your method.
responseJson variable is a Map, you should convert that map to the object you need.
I suggest taking a look at this.
Related
I'm getting data with this function:
Future<dynamic> getItem(String endpoint, List<String> pathParams) async {
final uri = buildUri(endpoint, pathParams, {});
final response = await http.get(uri, headers: {
'Authorization': 'Bearer $_ACCESS_TOKEN',
'Content-Type': 'application/json'
});
if (response.statusCode == _UNAUTHORIZED) {
return _refresh(
() => getItem(endpoint, pathParams), () => _redirectToLogin());
}
return response.body;
}
When I try to use the data like this:
List user = [];
void getItem() async {
List tmp = await ac.getItem("/v1/users/:0", [idProfile]);
if (mounted) {
setState(() {
user = tmp;
});
}
}
It sais me: it's not a subtype...
I've tried with List, List, List, Map, Map<String, dynamic>, and nothing works.
What type should I use?
I'm a new flutter developer.
So I want to create multiple filter lists with dropdowns...
This filter has 3 dropdown widgets, the expected result of this is that the search results can be combined with each other.
I'm kinda confused about how to start doing it, can you give me advice/reference/link related to this issue.
So far I just can do a single search (i got it from the search delegate)
Future<List<ModelKost>> getFilter({String? query}) async {
final prefs = await SharedPreferences.getInstance();
const key = 'token';
final value = prefs.get(key) ?? 0;
try {
var response = await http.get(Uri.parse('$serverUrl/home'), headers: {
'Accept': 'application/json',
'Authorization': 'Bearer $value'
});
if (response.statusCode == 200) {
data = json.decode(response.body)['data'];
results = data.map((e) => ModelKost.fromJson(e)).toList();
if (query != null) {
results = results
.where((e) =>
e.kabkot.toLowerCase().contains((query.toLowerCase())))
.toList();
}
} else {
debugPrint('fetch data error');
}
} on Exception catch (e) {
debugPrint('error: $e');
}
sortHarga = results;
return results;
}
How to implement it with multiple filters and with dropdown? thank you!
What you want to do is after the api call, store the result inside a list (for example allKosts). Then provide a getter to get the list, with the filter. Whenever you change a filter, you want to call setState and the getter's value will be updated automatically.
List<ModelKost> allKosts = [];
String kabkotFilter = '';
String tipeKotFilter = '';
List<ModelKost> get filteredKosts =>
results.where((e) => e.kabkot.toLowerCase().contains((kabkotFilter.toLowerCase())) && e.tipeKot.toLowerCase() == tipeKotFilter.toLowerCase())).toList();
I want to use CoinMarketCap API in flutter. But where I want to add data from map to list, an error will occur which says:
type 'string' is not a subtype of type 'int' of 'index'.
here's my code, I used this tutorial Migrating to the new CoinMarketCap API with Flutter
Future<void> getCryptoPrices() async{
List cryptoDatas = [];
print('Crypto Prices are Loading...');
String apiURL= "https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest";
http.Response response = await http.get(apiURL, headers: {'X-CMC_PRO_API_KEY': 'api code'});
Map<String, dynamic> responseJSON = json.decode(response.body);
if (responseJSON["status"]["error_code"] == 0) {
for (int i = 1; i <= responseJSON["data"].length; i++) {
cryptoDatas.add(responseJSON["data"][i.toString()]); // THE ERROR WILL HAPPEND HERE
}
}
setState(() {
this.cryptoList = cryptoDatas;
print(cryptoList);
});
Thank you in advance.
I had this same problem today, and I fixed it with this code. The code is a little different from yours but should do the same thing. If it didn't work then let me know.
Future<String> getCryptoPrices() async {
// API URL
var response = await http.get(
Uri.parse("API URL"),
// Only Accepts data in the formate of json
headers: {
"Accept": "application/json",
});
// this gets the data from the json
var first = json.decode(response.body);
//this is optional if you want to filter through the data
var second = first['current'];
var third = second['temp'];
// this prints out the data from the json
setState(() {
print(third);
});
}
change this line
cryptoDatas.add(responseJSON["data"][i.toString()])
to:
cryptoDatas.add(responseJSON["data"][i])
I am facing 2 problems with the below code and I think both are related.
createFunction is showing an error -
"This function has a return type of 'FutureOr< bool >', but doesn't end with a return statement. Try adding a return statement, or changing the return type to 'void'." - I need to return true or false, so I have to use return type bool.
When the function is executed, it runs smoothly till the PROBLEM AREA (marked in the code). Here it returns null and then comes back to execute .then . I need to run .then right after http.post is executed. At the end of the code it should return true / false.
Any help will be highly appreciated.
Future<bool> createFunction(image) async {
var request = new http.MultipartRequest("POST", Uri.parse(_urlImage));
request.files.add(
await http.MultipartFile.fromPath('imagefile', image));
var response = await request.send().catchError((error) {
throw error;
});
response.stream.transform(utf8.decoder).listen((value) async {
return await http
.post(
_url,
headers: {
'content-type': 'application/json',
'authorization': 'auth'
},
body: json.encode({data}),
)
///// PROBLEM AREA //////
.then((value) async {
final _extractedData = await jsonDecode(value.body);
if (value.statusCode == 201) {
return true;
} else {
return false;
}
}).catchError((error) {
throw error;
});
});
}
Ok, for the next visitors to this page, the correct usage of MultipartRequest class should like this:
var uri = Uri.parse('https://example.com/create');
var request = http.MultipartRequest('POST', uri)
..fields['user'] = 'nweiz#google.com'
..files.add(await http.MultipartFile.fromPath(
'package', 'build/package.tar.gz',
contentType: MediaType('application', 'x-tar')));
var response = await request.send();
if (response.statusCode == 200) print('Uploaded!');
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.