LateInitializationError: Field not initialized Error in Flutter - flutter

Can anyone help me with this problem?
I have the requester class, with the username attribute, as shown in the example below:
class Requester {
late String username;
}
I also have the getInformation() method, which is called in the "click" event, as shown in the example below:
getInformation() async {
Requester requester = Requester();
RequesterEndpoints endpoint = RequesterEndpoints();
final String token = "tokenExemplo";
final uri = Uri.parse(endpoint.getInformation);
final headers = {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Accept': 'application/json',
'Authorization': 'Bearer ${token}'
};
Response response = await get(uri, headers: headers);
dynamic responseBody = jsonDecode(response.body);
dynamic requesterBody = responseBody['requester'];
requester.username = requesterBody['username'];
}
The method, in the last line, changes, or should change, the value of the username attribute of the requester class. The requesterBody['username'] is a String type value, coming from an API. If I make one:
print(requesterBody['username'])
The username coming from the API will be displayed. That is, the value exists.
If I do a print on requester.username, right after requester.username = requesterBody['username'];, I can see that the username attribute was changed successfully.
I want to use this requester.username value in a view. I'm doing it this way:
import 'package:flutter/material.dart';
import 'package:mobile/models/requester.dart';
class HomeRequesterScreen extends StatefulWidget {
const HomeRequesterScreen({Key? key}) : super(key: key);
#override
State<HomeRequesterScreen> createState() => _HomeRequesterScreenState();
}
class _HomeRequesterScreenState extends State<HomeRequesterScreen> {
Requester requester = Requester();
#override
Widget build(BuildContext context) {
return Container(
child: Text(requester.username);
);
}
}
It is important to mention that the view is only called after the username attribute has been changed, in the getInformation() method.
But when I assign requester.username to Text, I get this error:
LateError (LateInitializationError: Field 'username' has not been initialized.)
In a direct way, I want to use the attribute value of a class in a view.
Does anyone know how to resolve this?

From the code that you shared:
in _HomeRequesterScreenState you just create a new instance of Requester and never assign any value to it. It does not contain anything.
Your getInformation() method is void, you create a variable there and never pass it anywhere even though you called the method.
In DTO classes, like your model, it's not a good practice to use late variables, if not for a reason. In your case, absolutely no need to.
So first, get rid of late, this way it would be easier for you understand if you are actually placing any data where you think it should be.
class Requester {
final String username;
Requester({required this.username});
}
Then make your method return your model.
Future<Requester> getInformation() async {
RequesterEndpoints endpoint = RequesterEndpoints();
final String token = "tokenExemplo";
final uri = Uri.parse(endpoint.getInformation);
final headers = {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Accept': 'application/json',
'Authorization': 'Bearer ${token}'
};
Response response = await get(uri, headers: headers);
dynamic responseBody = jsonDecode(response.body);
dynamic requesterBody = responseBody['requester'];
return Requester(username: requesterBody['username']);
}
Then explicitly create the instance in your business logic / state management level and pass it to UI.
Since I only have your UI code, let's assume we just do it there. Not to forget that while your API call is in progress, you don't have username to show, so you need to show something else instead and call setState once loaded.
import 'package:flutter/material.dart';
import 'package:mobile/models/requester.dart';
class HomeRequesterScreen extends StatefulWidget {
const HomeRequesterScreen({Key? key}) : super(key: key);
#override
State<HomeRequesterScreen> createState() => _HomeRequesterScreenState();
}
class _HomeRequesterScreenState extends State<HomeRequesterScreen> {
Requester? requester;
#override
void initState() {
super.initState();
loadRequester();
}
Future<void> loadRequester() async {
requester = await getInformation();
setState(() {});
}
#override
Widget build(BuildContext context) {
return Container(
child: requester != null ? Text(requester!.username) : CircularProgressIndicator();
);
}
}

Related

A value of type 'Future<void>' can't be assigned to a variable of type 'Future<DeviceModel>'

I am unsure on how to resolve this. I am trying to grab a specific device from an endpoint on my API.
class DeviceProfileWidget extends StatelessWidget {
final int deviceId;
DeviceProfileWidget({Key? key, required this.deviceId}) : super(key: key);
#override
Widget build(BuildContext context) {
Future<DeviceModel> device = Get.find<DeviceController>.
().getDevice(AppConstants.DEVICE_URI + deviceId.toString());
var ports = device.ports;
var port = ports.length;
print("device id is " + device.deviceId);
I can see that I am getting the data when I print my response.body in my device_api_client.dart file. However I am struggling to get this file to pass the deviceId so that I can grab a specific device. I dont want to grab the device from a filtered list, I want to hit the specific endpoint for the particular device. I can share more of my code if necessary.
Thanks in advance!
getDevice method is located here in controller file
class DeviceController extends GetxController {
final DeviceRepo deviceRepo;
DeviceController({required this.deviceRepo});
DeviceModel? _deviceModel;
DeviceModel? get device => _deviceModel;
Future<DeviceModel> getDevice(deviceURI) async {
Response response = await deviceRepo.getDevice(deviceURI);
if (response.statusCode == 200) {
_deviceModel = DeviceModel.fromJson(
response.body['device'] as Map<dynamic, dynamic>);
// print(_deviceModel);
update();
} else {
print("no data");
}
return DeviceModel(
deviceId: device!.deviceId,
publicId: device!.publicId,
label: device!.label,
temperatureImperial: device!.temperatureImperial, ports:
device!.ports);
}
}
In getDevice method please change the return to Future <DeviceModel> and return a DeviceModel from the method. Right now it's returning nothing and marked as Future<void>
You can pass it to this method by making those parameters
Future<DeviceModel> getDevice(deviceid, uri)
{
// All computation here
return DeviceModel(
//add device model details here like device ID etc
);
}
To get the deviceData use
DeviceModel deviceData = await getDevice();

Flutter Future returns instance of future [duplicate]

This question already has answers here:
What is a Future and how do I use it?
(6 answers)
Closed 9 months ago.
I am making an api call to receive data. When I make the call, I get back an instance of future. Why does this still return an instance of future instead of waiting for the data?
Here is my networking file
class NetworkHelper {
NetworkHelper(this.url);
final String url;
Future getSecureData(String token) async {
http.Response response = await http.post(
Uri.parse(url),
headers: {
HttpHeaders.authorizationHeader: token,
},
);
var data = response;
return data;
}
Here is my Account Settings file
class AccountSettings extends StatefulWidget {
const AccountSettings({Key? key}) : super(key: key);
static const String id = 'account_settings';
#override
State<AccountSettings> createState() => _AccountSettingsState();
}
class _AccountSettingsState extends State<AccountSettings> {
var userData;
#override
void initState() {
super.initState();
getUserData();
}
Future getUserData() async {
var token = await SecureStorage.getAccessToken();
var jwttoken = 'JWT ' + token!;
NetworkHelper networkHelper =
NetworkHelper('http://localhost:8000/auth/users/me');
userData = await networkHelper.getSecureData(jwttoken);
}
#override
Widget build(BuildContext context) {
print(userData);
return Scaffold(
Future getSecureData(String token) async {
http.Response response = await http.post(
Uri.parse(url),
headers: {
HttpHeaders.authorizationHeader: token,
},
);
var data = response; // This might be off.
var data = jsonDecode(response.body) // Try replacing with this.
return data;
}

The method 'getContacts' isn't defined for the type 'Type'

I'm new to the GetX framework and am trying the call the controller class function from the view using the Elevated button but it causes an error.
The method 'getContacts' isn't defined for the type 'Type'.
this is my contoller class
class ContactController extends GetxController {
var id;
#override
void onInit() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
id = preferences.getString('id');
print(id);
}
getContact() async {
// SERVER API URL
Uri url = Uri.parse('http://localhost:8000/get-contacts');
// Store all data with Param Name.
var data = {'sender': id};
//json encode
String? body = json.encode(data);
// Starting Web API Call.
var response = await http.post(url,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: body);
// Getting Server response into variable.
var contact = jsonDecode(response.body);
// If Web call Success than Hide the CircularProgressIndicator.
if (response.statusCode == 200) {
print(contact);
} else {
print("error");
}
}
}
this is my view class
class Contacts extends StatefulWidget {
const Contacts({Key? key}) : super(key: key);
#override
State<Contacts> createState() => _ContactsState();
}
class _ContactsState extends State<Contacts> {
final contactController = Get.put((ContactController));
#override
Widget build(BuildContext context) {
return Container(
child: ElevatedButton(
onPressed:()=>contactController.getContacts(),
child: Text("GET CONTACT")));
}
}
I can't able to call the function inside the elevated Button
onPressed:()=>contactController.getContacts(),
any one help me to solve this issue
Try changing it
final contactController = Get.put(ContactController());

How to post JSON to api in flutter? [duplicate]

I am trying to send a Json over HTTP post to update a record in my database. I've connected to the server but I'm getting a 415 "Unsupported Media Type" error when I run the request.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String url = 'http://<Hostname>:
<Port>/jderest/orchestrator/JDE_ORCH_Sample_UpdateMeterReadings_Generic';
Future<String> makeRequest() async {
var response = await http
.post(Uri.encodeFull(url), body: json.encode({
"NewHourMeterReading": "650",
"EquipmentNumber": "34665",
"NewFuelMeterReading": "650"
}), headers: {"Accept": "application/json"});
print(response.body);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new RaisedButton(
child: new Text('Make Request'),
onPressed: makeRequest,
)));
}
}
Can someone please let me know how to get past this error?
the error that I am facing is this.
I/flutter ( 5881): Unsupported Media Type
Screenshot of Response Headers/Status Code/Body
Sorry for the messy code, it didn't copy paste over every well.
You'll have to add the content-type to your header, setting its value to application/json.
By specifying Accept you're saying that your client is able to understand that response type, not that your request content is of the JSON type.
Basically you're saying "hey there, I'm able to understand JSON, so you can send it to me and I'll be fine with it" but you're not saying "hey I'm going to send you a JSON, be prepared for it!"
For a better understanding, you can find more about Accept here and Content-type here.
You are using incomplete headers for sending the json payload. That is why the server is not accepting you request.
Use the following headers instead:
headers: {
"content-type" : "application/json",
"accept" : "application/json",
},
Send Json and Accept Json using:-
Future<String> addData(Map<String, dynamic> request) async {
final url = 'http_url';
try {
final response = await http.post(url,
headers: {
"content-type" : "application/json",
"accept" : "application/json",
},
body: jsonEncode(request));
final responseData = jsonDecode(response.body) as Map<String,dynamic>;
return responseData['message'];
} catch (error) {
throw error;
}
}

Flutter - Send Json over HTTP Post

I am trying to send a Json over HTTP post to update a record in my database. I've connected to the server but I'm getting a 415 "Unsupported Media Type" error when I run the request.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String url = 'http://<Hostname>:
<Port>/jderest/orchestrator/JDE_ORCH_Sample_UpdateMeterReadings_Generic';
Future<String> makeRequest() async {
var response = await http
.post(Uri.encodeFull(url), body: json.encode({
"NewHourMeterReading": "650",
"EquipmentNumber": "34665",
"NewFuelMeterReading": "650"
}), headers: {"Accept": "application/json"});
print(response.body);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new RaisedButton(
child: new Text('Make Request'),
onPressed: makeRequest,
)));
}
}
Can someone please let me know how to get past this error?
the error that I am facing is this.
I/flutter ( 5881): Unsupported Media Type
Screenshot of Response Headers/Status Code/Body
Sorry for the messy code, it didn't copy paste over every well.
You'll have to add the content-type to your header, setting its value to application/json.
By specifying Accept you're saying that your client is able to understand that response type, not that your request content is of the JSON type.
Basically you're saying "hey there, I'm able to understand JSON, so you can send it to me and I'll be fine with it" but you're not saying "hey I'm going to send you a JSON, be prepared for it!"
For a better understanding, you can find more about Accept here and Content-type here.
You are using incomplete headers for sending the json payload. That is why the server is not accepting you request.
Use the following headers instead:
headers: {
"content-type" : "application/json",
"accept" : "application/json",
},
Send Json and Accept Json using:-
Future<String> addData(Map<String, dynamic> request) async {
final url = 'http_url';
try {
final response = await http.post(url,
headers: {
"content-type" : "application/json",
"accept" : "application/json",
},
body: jsonEncode(request));
final responseData = jsonDecode(response.body) as Map<String,dynamic>;
return responseData['message'];
} catch (error) {
throw error;
}
}