Trying to create a method to store Strings in a list - flutter

i have a list of volumes that looks like this
['9v9JXgmM3F0C','RoAwAAAAYAAJ','RYAwAAAAYAAJ']
i have a ready funtion that sends Individual volumes and retruns a Map.
Future<BookIdVolume> getBooksByVolume(volume) async {
var searchUrl = 'https://www.googleapis.com/books/v1/volumes/$volume';
var response = await http.get(searchUrl);
var responseBody = jsonDecode(response.body);
return BookIdVolume.fromJson(responseBody);
}
Im trying to create a method to store each of volumes in a list and retrun it.
I have tryed using loops for and forEach but it keeps retruning either [] or null
im i doing somthing wong ? is thier a better better way to do it ?

I'm guessing you're getting null back because you're not building the url properly for each volume. Try this.
final volumeList = ['9v9JXgmM3F0C', 'RoAwAAAAYAAJ', 'RYAwAAAAYAAJ'];
final baseUrl = 'https://www.googleapis.com/books/v1/volumes/';
List<BookIdVolume> bookList = [];
void buildBookList() async {
for (String volume in volumeList) {
final url = '$baseUrl$volume';
final book = await getBooksByVolume(url);
bookList.add(book);
}
}
Then you remove the first line from the getBooksByVolume function because you're already sending the full url.
Future<BookIdVolume> getBooksByVolume(url) async {
var response = await http.get(url);
var responseBody = jsonDecode(response.body);
return BookIdVolume.fromJson(responseBody);
}

Related

How to Save List in SharedPreferences in Flutter

Hello all at first I want to mention that I've tried a lot of solutions here but it didn't work for me.
I bring the list from the database through the following code:
var listCat = [];
Future getdata() async {
apiURL = '***************.php';
var response = await http.post(Uri.parse(apiURL));
var responsebody = jsonDecode(response.body);
if (responsebody.length >0){
for (int i = 0; i < responsebody.length; i++) {
listCat.add(responsebody[i]['name']+ ':' + responsebody[i]['image'].toString());
}
return responsebody;
}else{
}
}
As is obvious in the code above I am trying to get the name and image and this is not a problem right now I want to store this listCat in SharedPreferences until I recall it from all pages of the app
I have the following class to save SharedPreferences:
class APIPreferences {
static SharedPreferences ? _preferences;
static const _keyMuinCat = 'MuinCat';
static Future init() async => _preferences = await SharedPreferences.getInstance();
static Future setMuinCat(String MuinCat) async => await _preferences!.setString(_keyMuinCat, MuinCat);
static String? getMuinCat() => _preferences!.getString(_keyMuinCat);
}
Then I save what I need to save by the following line:
APIPreferences.setMuinCat(listCat.toString());
Then I can bring pre-stored data from any location where I need it through the following code:
CatList = APIPreferences.getMuinCat() ?? '';
I tried to do the following thing now to save the list in the first code above:
var listCat = [];
Future getdata() async {
apiURL = '***************.php';
var response = await http.post(Uri.parse(apiURL));
var responsebody = jsonDecode(response.body);
if (responsebody.length >0){
for (int i = 0; i < responsebody.length; i++) {
listCat.add(responsebody[i]['name']+ ':' + responsebody[i]['image'].toString());
APIPreferences.setMuinCat(listCat.toString());
}
return responsebody;
}else{
}
}
But it didn't work. I don't really know how to deal with it.
How can I save it and then bring it to use with ListView.
instead of:
_preferences!.setString(_keyMuinCat, "some string");
use:
_preferences!.setStringList(_keyMuinCat, ["some", "strings", "in", "list"]);
So in your code, the setMuinCat method needs to be:
static Future setMuinCat(List<String> muinCat) async => await _preferences!.setStringList(_keyMuinCat, muinCat);
and then you call it like this:
APIPreferences.setMuinCat((listCat as List).map((v) => v.toString()).toList());
To save the list in shared preferences you need to pass as jsonEncode(yourList data) and when you will fecth the shared list you will again jsonDecode(your list)
await prefs.setString('YOUR KEY', json.encode(YOURMAP()));

Flutter await does not await until return of function

I tried to find an answer but my problem is still there.
In my asynchronous upload function I return at the and the generated name of the image, which I want to use to make my database request.
This is my upload function:
Future<String> upload(File imageFile) async {
var stream =
new http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
// get file length
var length = await imageFile.length();
var uri = Uri.parse("http://localhost:8080/upload");
var request = new http.MultipartRequest("POST", uri);
var multipartFile = new http.MultipartFile('file', stream, length,
filename: basename(imageFile.path));
request.files.add(multipartFile);
var response = await request.send();
print(response.statusCode);
var createdFileName = "";
response.stream.transform(utf8.decoder).listen((value) {
createdFileName = value;
print(createdFileName);
});
return createdFileName;
}
I call it like this:
List createdFileNames = [];
for (var e in imagefiles) {
createdFileNames.add(await upload(File(e)));
}
I don't know why, but the createdFileNames are ["",""], but the upload gives as result the right name. In debug mode I can see, that the loop does not wait until the upload has finished.
Do you have any suggestions?
Thank you very much!
response.stream.transform(utf8.decoder).listen((value) {
createdFileName = value;
print(createdFileName);
});
This part in your function is asynchronous, it uses a callback.
But you don't wait for it to finish in any form. You just continue to return the createdFileName, that by that time most likely has not been filled.
I don't know what your stream looks like, if you only need the first value, you could await that instead of listening:
createdFileName = await response.stream.transform(utf8.decoder).first;
Replace
response.stream.transform(utf8.decoder).listen((value) {
createdFileName = value;
print(createdFileName);
});
with
createdFileName=await response.stream.bytesToString();
change code
for (var e in imagefiles) {
upload(File(e)).then((value) => createdFileNames.add(value));
}

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.

Flutter : How can use String data outside future method?

I have this future method to get a data from server and using it :
Future<String> get_week() async {
var weekUrl =
'https://xxx/api/controller/matchs/active_week.php';
var weekresponse = await http.get(weekUrl);
var weekdata = await jsonDecode(weekresponse.body);
var weekId = weekdata[0]['w_id'];
return weeId
}
How can i use the value of weekId outside this method?
You can use the await keyword to assign the returned value from the future to variable:
String id = await get_week();

Flutter - Best way to request Multiple APIs simultaneously

I have two URLs, and I am using the fetchData() function to parse the json.
Future<Iterable> fetchData() async {
var response = await http.get(firstUrl);
var listOne = List<Article>();
if (response.statusCode == 200) {
var notesJson = json.decode(response.body);
var bodyList = notesJson['items'];
for (var i in bodyList) {
listOne.add(Article.fromJson(i));
}
}
var resp = await http.get(secondUrl);
var listTwo = List<Article>();
if (resp.statusCode == 200) {
var notesJson = json.decode(resp.body);
var bodyList = notesJson['items'];
for (var i in bodyList) {
listTwo.add(Article.fromJson(i));
}
}
var newL = [...listOne, ...listTwo];
return newL;
}
I find this redundant. I want to know if this is the right approach, or can I optimize it? Since I am querying two URLs, should I be using compute() instead?
Flutter's compute spawns a whole other Isolate (thread-like things in Dart) and that's pretty resource-intensive for just waiting on a network request.
Gladly, Dart is event-loop-based, so you can wait on both requests simultaneously by simply wrapping both network request Futures in a call to Future.wait.
For more information about Dart's event loop, you might want to check out the explanatory video about Futures on Flutter's YouTube channel.
Future<List<Article>> fetchData() async {
var responses = await Future.wait([
http.get(firstUrl),
http.get(secondUrl),
]);
return <Article>[
..._getArticlesFromResponse(responses[0]),
..._getArticlesFromResponse(responses[1]),
];
}
List<Article> _getArticlesFromResponse(http.Response response) {
return [
if (response.statusCode == 200)
for (var i in json.decode(response.body)['items'])
Article.fromJson(i),
];
}
if you have dynamic list you can use Future.forEach method;
for example:
var list = ["https://first.api.url",
"https://second.api.url",
"https://third.api.url"];
void makeMultipleRequests(){
await Future.forEach(list, (url) async{
await fetchData(url);
});
}
Future<Iterable> fetchData(String url) async {
var response = await http.get(url);
print(response.body);
}
You can use Dio package.
response = await Future.wait([dio.post('/info'), dio.get('/token')]);