How to read HTTP POST request with the class return type in flutter? - flutter

how can I read the HTTP post response with the class return type?
my class is
class ContactModal {
String code;
String status;
String name;
ContactModal({this.code, this.status, this.name});
factory ContactModal.fromJson(Map<String, dynamic> json) {
return ContactModal(
code: json['code'],
status: json['status'],
name: json['name']
);
}
}
and my HTTP request is
class ApiClient {
Future<ContactModal> getDetails(String token) async {
print("inside get file "+token);
var response = await http
.get(Uri.parse(this.apiBaseUrl + "/file-list/"), headers: {
"Accept": "application/json",
"Authorization": token
});
if (response.statusCode == 200) {
print("Json response"+response.body);
return ContactModal.fromJson(json.jsonDecode(response.body));
} else {
print("Json exception response");
throw Exception('Failed to fetch access token');
}
}
}
my builder is
body: new Container(
child: new FutureBuilder(
future: apiClient.getFileDetails(this.accessToken),
builder: (context, snapshot) {
print(" prefs.getString('accessTokenValue') "+snapshot.data);
if (snapshot.hasData) {
print("Snap shot data : "+snapshot.data);
new ContactsList(_buildContactList(snapshot));
} else if (snapshot.hasError) {
return new Text("${snapshot.error}");
}
// By default, show a loading spinner
return new CircularProgressIndicator();
},
),
),
my api will return the response List[ContactModal]()
How can i read the all data and am getting everytime snapshot result null.

Your response contains array of contact json. So you might have to build the contact list and return like below.
var jsonArray = json.jsonDecode(response.body);
var contactList = jsonArray.map((json) => ContactModal.fromJson(json)).toList();
Return type of getDetails will be Future<List<ContactModal>>.

Related

Flutter rest api all my data is showing null

I am learning to use api and all data in my interface is showing as null
in this section to understand where the problem lies i change ! with ?
How can I check if there is a problem while pulling the data?
I deleted the irrelevant parts to shorten the code.
WeatherApiClient client = WeatherApiClient();
Hava? data;
Future<void> getData()async{
data = await client.getCurrentWeather("London");
}
#override
Widget build(BuildContext context) {
return MaterialApp(
body: FutureBuilder(
future: getData(),
builder: (context, snapshot){
if(snapshot.connectionState==ConnectionState.done){
return Column(
children: [
GuncelVeri(Icons.wb_sunny_rounded, "${data?.derece}", "${data?.sehir}"),
bilgiler("${data?.humidity}","${data?.feels_like}", "${data?.pressure}","${data?.description}"),],
);
}
else if(snapshot.connectionState == ConnectionState.waiting){
return Center(
child: CircularProgressIndicator(),
);
}
return Container();
},
)
),
);
}
}
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:weatherapp/model.dart';
class WeatherApiClient{
Future<Hava>? getCurrentWeather(String? location)async{
var endpoint = Uri.parse(
"https://api.openweathermap.org/data/2.5/weather?q=$location&appid=9b6ece44d1233c111b86cacb5e3617f1&units=metric&lang=tr"
);
var response = await http.get(endpoint);
var body = jsonDecode(response.body);
print(Hava.fromJson(body));
return Hava.fromJson(body);
}
}
Your are getting Null because you are trying to access the Hava class which have not been initilized yet.
You are printing print(Hava.fromJson(body));
before return Hava.fromJson(body);
First you want to check if what responce is getting from the http call.
for that you can just print the http responce like this:-
print(responce.body)
Then you can see what's the responce is.
They you can do return Hava.fromJson(body);
The right way
Check the status code of the responce, if the responce is 200 the cast the json responce to the model class or show an error
Refer code
Future<Profileclass> fetchprofile() async {
String tokenFetch = await getStringValuesSF();
return await Dio()
.get(urlprofiledio,
options: Options(
headers: {
'Authorization': 'Bearer $tokenFetch',
},
))
.then((response) {
if (response.statusCode == 200) {
return Profileclass.fromJson(jsonDecode(response.toString()));
} else {
throw Exception('Failed to load profile');
}
});
}
Thank you

is there a way i can fix my api request issue?

I did this but the (endPointUrl) after await get, is showing error, and having being have lot of issue, in which any url I use never responds always showing failed to locate localhost
import 'dart:convert';
import 'package:NewsApp/model/article_model.dart';
import 'package:http/http.dart';
class ApiService {
final endPointUrl =
"http://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=6ef7ae62a9e74ca2bcc7d634f9985146";
Future<List<Article>> getArticle() async {
Response res = await get(endPointUrl);
if (res.statusCode == 200) {
Map<String, dynamic> json = jsonDecode(res.body);
List<dynamic> body = json['articles'];
List<Article> articles =
body.map((dynamic item) =>
Article.fromJson(item)).toList();
return articles;
} else {
throw ("Can't get the Articles");
}
}
}
Your fetch method should be like this,
To fetch the whole data present in the given URL so use it where ever you want.
import 'dart:convert';
import 'package:NewsApp/model/article_model.dart';
import 'package:http/http.dart' as http;
class ApiService {
final endPointUrl =
"http://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=6ef7ae62a9e74ca2bcc7d634f9985146";
static Future<List<Article>> getArticle() async {
Response res = await http.get(Uri.parse(endPointUrl));
if (res.statusCode == 200) {
List json = jsonDecode(res.body);
// List<dynamic> body = json['articles'];
return
json .map((dynamic item) =>
Article.fromJson(item)).toList();
//return articles;
} else {
throw ("Can't get the Articles");
}
}
}
now suppose you retrieve the data in the following way.
FutureBuilder List<Article>(
future: ApiService.getArticle(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.bilder(
itemCount:snapshot.data.length,
itemBuilder: (context, position){
return Text(snapshot.data[position].article);
}
);
} else if (snapshot.hasError) {
return Text('error occurred');
} else {
return CircularProgressIndicator();
}
},
),

Get object data from future flutter

I have to check the email and password with the rest API that is going well. The problem is my future is returning a class object that has a token. I need that that for other screen and after login navigate to other screens.
Future<LoginResponse> createLoginState(String email, String password) async {
final http.Response response = await http.post(
'https://www.polestarkw.com/api/login',
headers: <String, String>{
'Accept': 'application/json',
//'content-type' : 'application/json'
},
body: {
"email":email ,
"password":password ,
});
if (response.statusCode == 200) {
// print(response.body);
LoginResponse loginResponse=LoginResponse.fromJson(json.decode(response.body)) ;
return loginResponse;
} else {
throw Exception('Failed to create album.');
}
}
class LoginResponse {
Object _data;
String token_type;
String expires_in;
String access_token;
String refresh_token;
LoginResponse(
{this.token_type, this.expires_in, this.access_token, this.refresh_token});
LoginResponse.fromJson(Map<String, dynamic> json) {
token_type = json['token_type'];
expires_in = json['expires_in'];
access_token = json['access_token'];
refresh_token = json['refresh_token'];
}
}
I need this loginResponse object on my other page. Here is using a future instance.
_futureJwt = createLoginState(emailController.text, pwdController.text);
how to get data from _futureJwt.
The code should go something like this
Future<LoginResponse> createLoginState(String email, String password) async {
final http.Response response = await http.post(
'https://www.polestarkw.com/api/login',
headers: <String, String>{
'Accept': 'application/json',
//'content-type' : 'application/json'
},
body: {
"email":email ,
"password":password ,
});
if (response.statusCode == 200) {
// print(response.body);
LoginResponse loginResponse=fromJson(json.decode(response.body)) ;
return loginResponse;
} else {
throw Exception('Failed to create album.');
}
}
LoginResponse fromJson(Map<String, dynamic> json) {
token_type = json['token_type'];
expires_in = json['expires_in'];
access_token = json['access_token'];
refresh_token = json['refresh_token'];
return LoginResponse(token_type,expires_in,access_token,refresh_token);
}
class LoginResponse {
Object _data;
String token_type;
String expires_in;
String access_token;
String refresh_token;
LoginResponse(
{this.token_type, this.expires_in, this.access_token, this.refresh_token});
}
The above code should work in the way u have written it too but I am not sure since I use this way
Then you can use this like
LoginResponse _futureJwt = await createLoginState(emailController.text, pwdController.text);
var token_type = _futureJwt.token_type;
var expires_in = _futureJwt.expires_in;
var access_token = _futureJwt.access_token;
var refresh_token = _futureJwt.refresh_token;
As simple as that. If you do not want to wait for the Future, you can use .then like this
createLoginState(emailController.text, pwdController.text).then((_futureJwt){
var token_type = _futureJwt.token_type;
var expires_in = _futureJwt.expires_in;
var access_token = _futureJwt.access_token;
var refresh_token = _futureJwt.refresh_token;
});
Use FutureBuilder.
Then you can use AsyncSnapshot to access hasData(), hasError() and get the data like so:
#override
Widget build(BuildContext context) {
Future<String> exampleFuture = Future.delayed(Duration(seconds: 2), "value")
return FutureBuilder(
future: exampleFuture,
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasError) {
return Text("error");
} else if (!snapshot.hasData) {
return Text("loading");
} else {
return Text(snapshot.data);
}
});
}

Flutter http request from Rapid Api not loading

I am tying retrieve data from an api on Rapid Api using Dart's http package and displaying it using Flutter however the content never loads and the api doesn't return an error.
class APIService {
// API key
static const _api_key = <MYAPIKEY>;
// Base API url
static const String _baseUrl = "covid-19-data.p.rapidapi.com";
// Base headers for Response url
static const Map<String, String> _headers = {
"content-type": "application/json",
"x-rapidapi-host": "covid-19-data.p.rapidapi.com",
"x-rapidapi-key": _api_key,
};
Future<CovidNumbers> fetchData(
{#required String endpoint, #required Map<String, String> query}) async {
Uri uri = Uri.https(_baseUrl, endpoint, query);
final response = await http.get(uri, headers: _headers);
if (response.statusCode == 200) {
return CovidNumbers.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load Data');
}
}
}
The method is then called onInit
Future<CovidNumbers> data;
APIService apiService = APIService();
#override
void initState() {
super.initState();
data = apiService.fetchData(
endpoint: "/country", query: {"format": "json", "name": "malta"});
}
And finally I display it in a FutureBuilder
FutureBuilder<CovidNumbers>(
//future: futureCovidNumbers,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(
"Confirmed Cases: ${snapshot.data.confirmed.toString()}");
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
));
The app remains stuck on the CircularProgressIndicator and does not display an error.
you future is empty, for that reason always is returning a CircularProgressIndicator, place your "data" variable inside the future and try again

How to do stream builder to get data from bloc in flutter

I am new in BLOC and I am trying to read respond from api.. but whenever I call stream builder... my widget always stops in wait... here is my code
here is api provider file
class Provider {
final _url = '...';
Future<List<LoginRespon>> login(a, b) async {
List<LoginRespon> datalogin = [];
try {
bool trustSelfSigned = true;
HttpClient httpClient = new HttpClient()
..badCertificateCallback =
((X509Certificate cert, String host, int port) =>
trustSelfSigned);
IOClient http = new IOClient(httpClient);
final response = await http.post(_url,
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
},
body: json.encode({
"aa": a,
"bb": b,
}));
Map<String, dynamic> responseJson = json.decode(response.body);
if (responseJson["status"] == "200") {
datalogin.add(LoginRespon(
status: responseJson['status'],
data: Data(
name: responseJson['data']['name'],
position: responseJson['data']['pos'])));
return datalogin;
} else {
print("ppp");
}
} on Exception {
rethrow;
}
return datalogin;
}
}
and here is for stream builder
isClick
? StreamBuilder(
stream: bloc.login(),
builder: (context, snapshot) {
if (snapshot.hasData) {
print(snapshot.data);
return Text("success");
} else if (snapshot.hasError) {
return Text(
snapshot.error.toString());
}
return Text("wait..");
},
)
: FlatButton(
child: Text("Login"),
onPressed: () {
setState(() {
isClick = true;
});
},
),
is there a way so that I can call print(snapshot.data) inside if (snapshot.hasData)
You need to pass argument which required in method otherwise it will not successfully responce (200) and it will throw error.