json Fetch rerun - flutter

So i'm writting app in which i fetch data from air quality index webpage www.waqi.info and display it. So i got it working for one city but when i change city on popuplist how to recall api with different url. Tried something but it doesn't work. Now i have idea to save city in phone memory and then reruning app. Any clues how i can recall Http request for different city almost same url but how to recall http request from onchange. Im new to flutter and dart. Sorry for any stupidty

you have to use http 0.12.0+2 library to do API calls http library page
you can simply create a function which will fetch data
getData(city) async{
String url="YOUR_URL_HERE?city="+city;
var response=await http.get(url);
return response.body;
}
You can call this method from your onChanged

you can use a function to call api and pass city name as argument
like this
callApi(city) async{
String url="Url/${city}";
var response=await http.get(url);
return response.body;
}
and after getting response set data drom response to model object and then call setState()
which will reset your whole screen

Related

How to parse json list into a string - Tweak the code so that I can display a single Json, just as I can display a List of Json

I am getting this error:
A value of type 'UserModel' can't be assigned to a variable of type 'List<UserModel>'.
I am using Postman to generate my api service code (http request that get api from internet). And I am using https://app.quicktype.io/ to generate my User Model class.
I saw a flutter tutorial which parsed json into a List because the json was actually a List itself. But In this case, Json is a single item (see pictures for difference). How do i Parse it? and display in a ListView.builder widget?
You can re create this problem using this api link: https://reqres.in/api/users?page=1
My code snippet to parse json into a List is:
if (response.statusCode == 200) {
String tempStoreDataFromApi = await response.stream.bytesToString();
List<DataModel> dataList_1 = dataModelFromJson(tempStoreDataFromApi);
Samples for how a List of json looks, vs how a single item of json looks.
Your api response is a Map. You should use ["data"] on it if you want to access the list inside it, like this:
List<UserModel> userModelFromJson(String str)-> List<UserModel>.from(((json.decode(str)["data"]) as List).map((x)-> UserModel.fromJson(x)));

Google Books API not returning the same as displayed on browser (Flutter)

I am building a book app with Flutter for Android and iOS. I am using Google Books API to retrieve book data, but I have noticed something strange which I dont understand. If we look at the book data displayed in chrome browser (https://www.googleapis.com/books/v1/volumes/b3GuDwAAQBAJ), we can see that the content (eg. field categories) is different than what I get when calling http response and printing out it's body. In addition to that, it also seems like unicode characters (eg. from description) are not sent.
The code that I'm using to get the API data can be seen below:
Response result = await http.get(Uri.parse(url), headers: {'content-type': 'application/json; charset=utf-8'});
if (result.statusCode == 200) {
final jsonResponse = jsonDecode(utf8.decode(result.bodyBytes));
if (jsonResponse["totalItems"] == 0) {
return List.empty();
}
//this prints out the content in above image
print(result.body.toString());
final booksMap = jsonResponse['items'];
List<dynamic> books = booksMap.map((i) => Book.fromJson(i)).toList();
return books;
It seems that https://www.googleapis.com/books/v1/volumes/b3GuDwAAQBAJ gives different data than your usual search query (eg. https://www.googleapis.com/books/v1/volumes?q=isbn:9780143123231). I do not know the reason why.
You can see the API response in raw form due to which unicode are present
Raw Form image from browser
but when you get api response you can parse into json, By parsing json that unicodes are removed and data is in proper format
if you use json Formatter extension in chrome you can see that the data in chrome in Json form and the response from api when you are hitting api by code are same.
Data in Json Form in Browser
in the application code , you set headers: {'content-type': 'application/json; thats why u received Json data code. and its not problem because you will use this data into your application,
you can see more content types here
Blockquote

How to add new data into Future<dynamic> in dart / flutter?

I am developing a chat system in mobile application using Flutter / Dart.
I have fetched a user's message records from server by API and received result as Future<dynamic>. This result has list of chat data. If I pass it to FutureBuilder widget. It works and lists chat records in listTile. Everything is working well.
When user adds a new chat message then I post the that text message to server by API to store into database. It works and response status is 200 which means message has been added on server's database.
I have instance of newly added chat message, I want to append / add it to previously fetched Future<dynamic> result.
Kindly suggest me how can I do this? Can we update Future<dynamic> typed data? Thanks.
Future can emit only one item by design. If you want to emit multiple items, use Stream: https://api.flutter.dev/flutter/dart-async/Stream-class.html
To get to know how to generate streams have a look on this: https://dart.dev/articles/libraries/creating-streams
Most likely what you want to do is use rxdart's BehaviorSubject or dart's StreamController (they share api, so just substitute the name, except for ValueStream, which is specific to rxdart, this one will have to be replaced with just Stream):
class Api {
final _subject = BehaviorSubject<DataToDisplay>();
ValueStream<DataToDisplay> get data => _subject.stream;
void fetchData() {
final data = downloadDataFromSomewhere();
_subject.add(data);
}
}
Then just create a StreamBuilder similarly to FutureBuilder.

URL interpolation using Uri class

I'm having an issue with the Uri class, the code below used to work before the updates but now, the issue is that it uses a String instead of a Uri URL, I've been trying to update this interpolation to the newest standard with no success. This URL is simply getting data from Firebase with tokens from users that are signed in.
final response = await http.get("$_url.json?auth=$_token");
I already managed parse the main part of the url:
Uri _url = Uri.parse("https://my-project.firebaseio.com/example");
The final result used to be something like this:
https://my-project.firebaseio.com/example.json?auth=xLwOQ2GEQxPp0h0QD1foHgSyXR52
How do I interpolate this URL properly since I have one value that isn't static? (_token)
You should use the Uri.https constructor to create the Uri you then use with get.
For example
var uri = Uri.https('my-project.firebaseio.com', '/example', queryParameters: {'auth': _token})
See Uri.http documentation

How do you get a documentSnapshot from firestore over a cloud function in flutter?

a bit of intro first, I need to get the documentSnapshot and not only the data of a record which is in Firestore because I have pagination in my app, and to do that, when you query you need to send the last documentSnapshot from where your query will send the 10 next records.
So, this worked fine with the SDK, but I want to implement Cloud Functions now, and when I try to respond with a documentSnapshot from the cloud function I am not able to get the documentSnapshot in Flutter.
This is the portion of code where the issue is:
final function = _cloudFunctions.getHttpsCallable(
functionName: 'createRecord',
);
try {
final response = await function.call(data);
final DocumentSnapshot doc = response.data;
return doc;
} catch (e) {
print(e)
return null;
}
Whith this code I get the error: type '_InternalLinkedHashMap' is not a subtype of type 'DocumentSnapshot'
Is there a workaround or I am doing something wrong?
The response from a callable Cloud Function is not going to be a strongly typed DocumentSnapshot. That's what the error message is trying to tell you. You're getting a map type object, and you have to deal with that object as such. You can't just force it to be a DocumentSnapshot.
If you're using your callable function as a tool for pagination, you won't be able to pass DocumentSnapshot objects back and forth between the client and function. You're going to have to pass the function enough information to paginate without providing a DocumentSnapshot.
A DocumentSnapshot is not actually required to paginate - what you do need is enough information to tell the query to pick up where it left off, as shown in the documentation. This involves using startAt or startAfter using information from the last document seen.