In a Future Builder im trying to use two methods with different types, both of them fetch data from the api,
the main problem that im having is that both of the function have different types, so im having problem on putting
the two methods because of their types. I tried using
Future.wait(Future[]) aswell but i was getting many errors, there errors where mostly on List,
im still trying to learn how Future Builders work, i worked with FutureBuilders before but didnt have to use two functions inside the FutureBuilder. So if anyone could implement their solution on my code, that would really help and maybe add some comments on why did you make the change so i learn for the future. As a bonus im getting the List is not a subtype of type Map<String, dynamic> error aswell so if anyone could help with that too it would be very helpful. Tried looking into stack over flow answers for that but i couldnt figure it out since i was getting an error on this part
buildSwipeButton() {
return MenuPage(
sendData: fetchLoginData()// i was getting error here,
);
}
buildSwipeButton() {
return MenuPage( // other class name from a different file
sendData: fetchLoginData(),
);
}
buildSwipeButton2() {
return MenuPage( // other class name from a different file
sendData2: fetchWorkingLocationData(),
);
}
Future<LoginData>? fetchLoginData() async {
var url = 'https://dev.api.wurk.skyver.co/api/employees';
String basicAuth = 'Basic ' +
base64Encode(
utf8.encode('${emailController.text}:${passwordController.text}'),
);
var response = await http.get(
Uri.parse(url),
headers: <String, String>{'authorization': basicAuth},
);
print(response.body);
if (response.statusCode == 200) {
print(response.statusCode);
return LoginData.fromJson(
jsonDecode(response.body),
);
} else {
throw Exception('Failed to load LoginData');
}
}
Future<WorkingLocationData>? fetchWorkingLocationData() async {
var url = 'https://dev.api.wurk.skyver.co/api/locations';
String basicAuth = 'Basic ' +
base64Encode(
utf8.encode('${emailController.text}:${passwordController.text}'),
);
var response2 = await http.get(
Uri.parse(url),
headers: <String, String>{'authorization': basicAuth},
);
print(response2.body);
if (response2.statusCode == 200) {
print(response2.statusCode);
return WorkingLocationData.fromJson(
jsonDecode(response2.body),
);
} else {
throw Exception('Failed to load Working Location Data');
}
}
// other file where im trying to use Future Builder
late LoginData data;
Future<LoginData>? sendData;
Future<WorkingLocationData>? sendData2;
body: FutureBuilder<LoginData>(
future: sendData, // trying to use sendData and sendData2
builder: (context, snapshot) {
if (snapshot.hasData) {
LoginData? data1 = snapshot.data;
data = data1!;
print(data.loginPhoneNumber);
return afterLoginBody();
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return Center(child: const CircularProgressIndicator());
},
),
),
Try below code hope its help to you.
late LoginData data;
Future<LoginData>? sendData;
Future<WorkingLocationData>? sendData2;
body: FutureBuilder<LoginData>(
Future.wait([sendData, sendData2]),
builder: (context, AsyncSnapshot<List<dynamic>> snapshot{
snapshot.data[0]; //sendData
snapshot.data[1]; //sendData2
},
),
),
You can try this:
Future? _future;
Future<dynamic> sendData() async {
final data1 = await sendData1();
final data2 = await sendData2();
return [data1, data2];
}
#override
void initState() {
_future = sendData()();
super.initState();
}
///
FutureBuilder(
future: _future,
builder: (context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CupertinoActivityIndicator();
}
if (snapshot.hasError) {
return SomethingWentWrong();
}
final data1= snapshot.data[0] as YourDataModel;
final data2 = snapshot.data[1] as YourDataModel;
});
Related
I got FutureBuilder snapshot error when I parsing my JSON i got the:
type 'List' is not a subtype of type 'FutureOr<List>'
is it my Product model error or a parsing error?
my code
late Future<List<Product>> productFuture = getProducts();
static Future<List<Product>> getProducts() async {
var url = '${Constants.API_URL_DOMAIN}action=catalog&category_id=$id';
final response = await http.get(Uri.parse(url));
final body = jsonDecode(response.body);
print(body['data']);
return body['data'].map((e)=>Product.fromJson(e)).toList();
}
FutureBuilder<List<Product>>(
future: productFuture,
builder: (context, snapshot) {
print(snapshot);
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasData) {
final catalog = snapshot.data;
return buildCatalog(catalog!);
} else {
print('SNAPSOT DATA ${snapshot.data}');
return Text("No widget to build");
}
}),
Use List.from
return List.from(body['data'].map((e)=>Product.fromJson(e)));
static Future<List<Product>> getProducts() async {
var url = '${Constants.API_URL_DOMAIN}action=catalog&category_id=$id';
final response = await http.get(Uri.parse(url));
final body = jsonDecode(response.body);
print(body['data']);
return List.from(body['data'].map((e)=>Product.fromJson(e)));
}
Try to convert all List<Product> --> List<dynamic>
Hi guys I'm new to Flutter
I'm trying to fetch the data from http.post method using FutureBuilder and snapshot.data but it keeps returning CircularProgressIndicator which is means snapshot has no data.
Future postDataTransaksi() async {
try {
http.Response response = await http.post(
Uri.parse('https://ignis.rumahzakat.org/donol/listTransaksi'),
body: {
'---': '---',
'---': '---',
},
headers: {
'access-token': '---'
});
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
} else {}
} catch (e) {
print(e.toString());
}
}
This is my post method code.
FutureBuilder(
future: postDataTransaksi(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Container(child: Text(snapshot.data[0]['id']));
} else {
return const Center(child: CircularProgressIndicator());
}
})
And this is how I try to fetch the data
Change your builder to this:
if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
return Container(child: Text(snapshot.data[0]['id']));
} else {
return const Center(child: CircularProgressIndicator());
}
and also change your future to this"
Future<List> postDataTransaksi() async {
try {
http.Response response = await http.post(
Uri.parse('https://ignis.rumahzakat.org/donol/listTransaksi'),
body: {
'---': '---',
'---': '---',
},
headers: {
'access-token': '---'
});
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
return data;// <--- add this
}
return [];// <--- add this
} catch (e) {
print(e.toString());
return [];// <--- add this
}
}
I been reading multiple threads about passing data between futures, but for some reason I can get this to work.:(
I have two futures, where the first future is doing post request to retrieve a token
Future<AuthStart> fetchAuthStart() async {
final response = await http.post(
Uri.parse('http://ipsum.com/auth/start'),
body: jsonEncode(<String, String>{
'IdNumber': '198805172387',
}));
if (response.statusCode == 200) {
final responseJson = jsonDecode(response.body);
return AuthStart.fromJson(responseJson);
} else {
throw Exception("Failed");
}
}
this request will generate an GUID that I need in my next future
Future<AuthStatus> fetchAuthStatus(String token) async {
final response = await http.post(Uri.parse('http://ipsum/auth/status'),
body: jsonEncode(<String, String>{
'Token':token,
}),
);
if (response.statusCode == 200) {
return AuthStatus.fromJson(jsonDecode(response.body));
} else {
throw Exception("Failed");
}
}
I have tried multiple ways, one that worked was to pass the variable in my FutureBuilder like this
FutureBuilder(
future: futureAuthStart,
builder: (context, snapshot) {
if (snapshot.hasData) {
fetchAuthStatus(snapshot.data!.Token);
return Text(snapshot.data!.Token);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
),
But this does not make sense?
I would rather pass it in my InitState something like this.
void initState() {
super.initState();
futureAuthStart = fetchAuthStart();
futureAuthStatus = fetchAuthStatus(token);
}
Am I totally on the wrong path? Any tutorials out there that can give better info :)?
Thanks in advance.
Create a void function and pass it the functions and one at a time it will be executed with async/await. You should take a look at Asynchronous programming: futures, async, await.
void initState() {
super.initState();
_onInit();
}
void _onInit() async {
try {
var futureAuthStart = await fetchAuthStart();
var futureAuthStatus = await fetchAuthStatus(futureAuthStart.data.token);
}catch(e, stackTrace){
//handler error
print(e);
print(stackTrace);
}
}
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
I want to get List values as ints one by one.
where movieId requires an int value.
help me please
thank you
Future<MovieDetailModel> getMovieDetail(int? movieId) async {
try {
http.Response res = await http
.get(Uri.parse('$mainUrl/movie/$**movieId**?$apiKey&language=ko-KR'))
.timeout(Duration(seconds: 8),
onTimeout: () async => new http.Response('{}', 404));
if (res.statusCode == 404) {
return MovieDetailModel.fromJson({});
}
Map<String, dynamic> result = jsonDecode(res.body);
MovieDetailModel movies = MovieDetailModel.fromJson(result);
return movies;
} catch (e) {
print('MovieDetail $e');
}
return MovieDetailModel.fromJson({});
}
where user.userMovieId value is List .
Widget userMovie(UserModel user) {
return FutureBuilder(
future: this._movieDetailProvider.movies(**user.userMovieId!**),
builder:
(BuildContext context, AsyncSnapshot<MovieDetailModel> snapshot) {
if (snapshot.hasData) {}
Provider.
Future<MovieDetailModel> movies(int movieId) async {
MovieDetailModel movieList = await _movieRepo.getMovieDetail(movieId);
notifyListeners();
return movieList;
}