The method 'getUserData' was called on null. Receiver: null Tried calling: getUserData() - flutter

I'm trying to get the user's currency from my server. Until now I'm able to do that but the problem is the data keeps rebuild itself everytime the app gets rebuilt. I tried to fix that by this way :
Future<dynamic> userDataFuture;
ApiService apiService;
#override
void initState() {
userDataFuture = apiService.getUserData();
super.initState();
}
but fails as it gives me an error saying :
The method 'getUserData' was called on null. Receiver: null Tried calling: getUserData()
this is my ApiService Class
Future getUserData() async {
String token = await AuthProvider().getToken();
String userID = await AuthProvider().getUserId();
final response = await Dio().get(
'$apiUrl/$userID',
options: Options(headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $token',
}),
);
if (response.statusCode == 200) {
return response.data;
} else {
throw Exception('Failed to load data');
}
}
this is my UI where I want to show the user's currency:
child: Center(
child: FutureBuilder(
future: userDataFuture,
builder:
(BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasError) {
return Center(
child: Text(
"Something wrong with message: ${snapshot.error.toString()}"),
);
} else if (snapshot.connectionState ==
ConnectionState.done) {
return Text(
snapshot.data[
'currency'], // This Should Change Depending in Settings of the User
style: TextStyle(
fontSize:
(device.localWidth * .1) * .43,
fontWeight: FontWeight.w500,
color: kLightTextColor));
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
// ),
),
),

You're calling getUserData() on an ApiService object that is not initialized -- ie. null.
Instead of this
ApiService apiService;
Actually initialize it like this
final apiService = ApiService();
That will get rid of your null error. You can also just pass apiService.getUserData() into your FutureBuilder and get rid of the userDataFuture object altogether.

first of all you have to use await, here like this
userDataFuture = await apiService.getUserData();
second you have to initialize you'r apiService variable like this:
ApiService apiService = new ApiService();
third, change you'r getUserData to return some data, it's void function.
fourth one you have to use somethink like this:
setState(() {
userDateFuture = await apiService.getUserData();
});
i hope, i was able to help.

Related

How to add json to an autocomplete widget in flutter

Im trying to pass the data from an API to a list so that I can view it in the Autocomplete widget but I keep getting errors. I tried below code.
This is the code I have tried which passes data to the autocomplete as instance of 'Bus'
GetBuilder<BusesListController>(
init: BusesListController(),
builder: (_) {
_.viewPartners();
return DottedBorder(
child: Padding(
padding:
const EdgeInsets.only(left: 8.0),
child: Autocomplete<Bus>(
optionsBuilder: (TextEditingValue
textEditingValue) {
List<Bus> partnercos = [];
partnercos = _.partners.value as List<Bus>;
// (_.partners).map((value) => Bus.fromJson(value as Map<String, dynamic>)).toList();
print(partnercos);
return partnercos
.where((bus) => bus.company!
.toLowerCase()
.contains(textEditingValue
.text
.toLowerCase()))
.toList();
},
)),
);
}),
I also tried passing _.partners directly but it doesn't work either
Other fix I tried is passing _.partners instead of _.partners. Value above which invokes errors in arena.dart in void _tryToResolveArena which shows that state. Members.length == 1 hence scheduleMicrotask(() => _resolveByDefault(pointer, state));
Contoller code
class BusesListController extends GetxController {
var partners = [].obs;
var isLoaded = false.obs;
final loginController = Get.put(LoginController());
Future<void> viewPartners() async {
final token = loginController.rxToken.value;
var headers = {
'Authorization': 'Bearer $token'
};
try {
var url =
Uri.parse(ApiEndPoints.baseUrl + ApiEndPoints.endpoints.listBusAdmin);
http.Response response = await http.get(url, headers: headers);
if (response.statusCode == 200) {
final json = jsonDecode(response.body);
partners. Value =
(json as List).map((json) => Bus.fromJson(json)).toList();
isLoaded.value = true;
} else {
throw jsonDecode(response.body)["Message"] ?? "Unknown Error Occured";
}
} catch (error) {
// Get.snackbar('Error', error.toString());
}
}
#override
void onInit() {
super.onInit();
viewPartners();
}
}
I am able to print the response so I know the api works but I'm having problems with passing partners list into the autocomplete

call parameter function to get data in flutter

I'm learning and trying to add parameters when calling parameters in functions when getting data from the API, but I'm a bit confused about how I call them in widgets.
static Future<Map<String, DataKuliahModel>> getDataKuliah(String smt) async {
String url = Constant.baseURL;
String token = await UtilSharedPreferences.getToken();
await Future.delayed(const Duration(milliseconds: 1000));
// String responseJson = await rootBundle.loadString('assets/1.json');
Map<String, DataKuliahModel> finalResult = {};
final response = await http.get(
Uri.parse(
'$url/auth/mhs_siakad/perwalian/get_paket',
),
headers: {
'Authorization': 'Bearer $token',
},
);
final result = jsonDecode(response.body)['data'] as Map<String, dynamic>;
result.forEach((key, value) {
DataKuliahModel dataKuliah = DataKuliahModel.fromMap(value);
finalResult.addAll({
key: dataKuliah,
});
});
return finalResult;
}
and I want to call him here
When you declare a function with positional parameters you need to provide those parameters when you call that function.
import 'package:flutter/material.dart';
class Services {
static Future<String> greeting(String name) async {
/// this function doesn't need to be Future
/// but when you call API to get some data it should be a Future
return 'Hello $name';
}
}
class MyWidget extends StatelessWidget {
const MyWidget({super.key});
#override
Widget build(BuildContext context) {
return FutureBuilder(
/// pass positional parameter to [greeting] here
future: Services.greeting('Dash'),
builder: (context, AsyncSnapshot<String> snapshot) {
return Center(
child: Text(snapshot.data ?? 'default'),
);
},
);
}
}
Result: Hello Dash
In your case smt seems to be an int not a String
and you have to pass it as query parameter to http request as follows
static Future<Map<String, DataKuliahModel>> getDataKuliah(int smt) async {
String url = Constant.baseURL;
String token = await UtilSharedPreferences.getToken();
await Future.delayed(const Duration(milliseconds: 1000));
// String responseJson = await rootBundle.loadString('assets/1.json');
Map<String, DataKuliahModel> finalResult = {};
final response = await http.get(
// Uri.parse(
// '$url/auth/mhs_siakad/perwalian/get_paket',
// ),
Uri.http(url, '/auth/mhs_siakad/perwalian/get_paket',
{'smt':smt}),
headers: {
'Authorization': 'Bearer $token',
},
);
final result = jsonDecode(response.body)['data'] as Map<String, dynamic>;
result.forEach((key, value) {
DataKuliahModel dataKuliah = DataKuliahModel.fromMap(value);
finalResult.addAll({
key: dataKuliah,
});
});
return finalResult;
}
Have you looked at the Uri replace method?
You can do the following:
Uri.parse('$url/auth/mhs_siakad/perwalian/get_paket').replace(queryParameters:{ "smt":"$smt"});
Update on FutureBuilder:
// Put this outside your build function
Future<Map<String, DataKuliahModel>> DK ;
// Put this in your initState if you want the future to run on page load or use it for events like onTap
DK = Service.getDataKuliah(<PARAM>);
// This is in your build method
FutureBuilder(
future:DK,
builder: (context, snapshot) {
// add wigets to display results here
}
)

Flutter Multiple functions in a FutureBuilder

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;
});

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

Flutter: FutureBuilder How can I load a future that receives arguments?

I am working with a FutureBuider and I don't know how I can load a Future that receives an argument. I get an error, the future is in an external file 'provider.dart', I attach an image of the error:
1 positional argument(s) expected, but 0 found.
Try adding the missing arguments.dart(not_enough_positional_arguments)
To explain myself better I have to mention the structure of the application:
HomePage: in it you select an image that will be sent to a 'provider.dart' file.
PhotoPage: On this page, a value obtained from the Provider.dart file is obtained through a FutureBuilder, as shown in the image above.
children: [
FutureBuilder(
future: fotoProvider.uploadImageCloudinary(),
builder: (context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasError) {
return Center(
child: Text('ERROR: ${snapshot.error.toString()}'),
);
}
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return Center(
// I WOULD LIKE TO PRESENT THE RESULTS OF THE SECOND FUTURE HERE
child: Text(snapshot.data),
);
},
),
],
),
Provider.dart: There are two Future's:
1 Future: It receives the image from the home and processes it sending it to the Cloudinary API, I get the url generated by Cloudinary to be sent to the second Future.
Future<String> uploadImageCloudinary(File imagen) async {
final url = Uri.parse('https://api.cloudinary.com/...');
final mimeType = mime(imagen.path).split('/'); // Image/jpeg
final imageUploadRequest = http.MultipartRequest('POST', url);
final file = await http.MultipartFile.fromPath(
'file',
imagen.path,
contentType: MediaType(mimeType[0], mimeType[1]),
);
imageUploadRequest.files.add(file);
// execute request
final streamResponse = await imageUploadRequest.send();
final resp = await http.Response.fromStream(streamResponse);
if (resp.statusCode != 200 && resp.statusCode != 201) {
print('Something went wrong');
print(resp.body); // Error
return null;
}
dynamic respData = json.decode(resp.body);
print(respData);
urlGenCloudinary = respData['secure_url'];
// Shipment to the second future
return await requestSecondAPI(urlGenCloudinary);
}
2 Future: It receives the url and sends it to another API, this one processes it and generates a String that is the data that I want to be sent to FutureBuilder in FotoPage.
Future requestSecondAPI(String url) async {
final String apiUrl =
"https://api...";
final res = await http.post(
Uri.parse(apiUrl),
headers: {
"Content-type": "application/json",
"Authorization": "Key "
},
body: jsonEncode({
"inputs": [
{
"data": {
"image": {'url': url}
}
}
],
"model": {
"output_info": {
"output_config": {"max_concepts": 40, "min_value": 0.8}
}
}
}),
);
final resReqRes = reqResRespuestaFromJson(res.body);
String resultado = resReqRes.outputs[0].data.concepts[0].id;
return resultado;
}
Thank you in advance.
I tried to place the second Future in the FutureBuilder and I get the following errors:
In FutureBuilder:
"Couldn't infer type parameter 'T'. "
In the future within the FutureBuilder:
"1 positional argument(s) expected, but 0 found.
Try adding the missing arguments."
In the builder:
"The argument type 'Center Function(BuildContext, AsyncSnapshot)' can't be assigned to the parameter type 'Widget Function(BuildContext, AsyncSnapshot)' "