Below is how my json looks like
{
"data": {
"id": 2,
"email": "[email protected]",
"first_name": "Valjakudze",
"last_name": "shipment",
"avatar": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7e/Circle-icons-profile.svg/1024px-Circle-icons-profile.svg.png"
}
}
I am using Dio and below are my two classes for the responses
Response Class
import 'package:json_annotation/json_annotation.dart';
import 'package:json_crud/classes/user.dart';
part 'user_response.g.dart';
@JsonSerializable()
class UserResponse{
@JsonKey(name: "data")
User? user;
UserResponse();
factory UserResponse.fromJson(Map<String, dynamic> json) => _$UserResponseFromJson(json);
Map<String, dynamic> toJson() => _$UserResponseToJson(this);
}
Below is my UserClass
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
@JsonSerializable()
class User{
@JsonKey(name: "id")
late int id;
@JsonKey(name: "email")
late String email;
@JsonKey(name: "first_name")
late String firstName;
@JsonKey(name: "last_name")
late String lastName;
@JsonKey(name: "avatar")
late String avatar;
User();
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
Below is my UserProfileScreen where i am supposed to set text
import 'dart:developer';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:json_crud/classes/user.dart';
import 'package:json_crud/classes/user_response.dart';
import 'package:json_crud/http_service.dart';
class UserProfile extends StatefulWidget {
const UserProfile({Key? key}) : super(key: key);
@override
_UserProfileState createState() => _UserProfileState();
}
class _UserProfileState extends State<UserProfile> {
HttpService? httpService;
UserResponse? userResponse;
User? user;
bool isLoading = false;
Future getUser () async {
Response response;
try {
log("TryCatchCalled");
response = await httpService!.getRequest("/b/BGT5");
if(response.statusCode == 200){
setState(() {
userResponse = UserResponse.fromJson(response.data);
user = userResponse!.user;
log("ResponseStatusCode200 ${response.statusCode}");
});
}else{
log("ResponseStatusCode ${response.statusCode}");
}
} on Exception catch (e) {
isLoading = false;
log("GetUserResponseException ${e.toString()}");
}
}
@override
void initState() {
httpService = HttpService();
userResponse = UserResponse();
user = User();
getUser();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("User Profile"),
),
body: isLoading
? const Center(child: CircularProgressIndicator())
: Container(
width: double.infinity,
child: Column(
children: [
Image.network(user!.avatar),
Container(height: 16,),
Text("Hello, ${user!.firstName} ${user!.lastName}")
],
),
),
);
}
}
I am getting LateInitializationError: Field 'avatar' has not been initialized error
Below is what i have tried by changing my user class
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
@JsonSerializable()
class User{
@JsonKey(name: "id")
int? id;
@JsonKey(name: "email")
String? email;
@JsonKey(name: "first_name")
String? firstName;
@JsonKey(name: "last_name")
String? lastName;
@JsonKey(name: "avatar")
String? avatar;
User();
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
But when i do the above when i change class variables from late i get a new error Error: The argument type 'String?' can't be assigned to the parameter type 'String' because 'String?' is nullable and 'String' isn't. Image.network(user!.avatar),
below is the full error log
======== Exception caught by widgets library =======================================================
The following LateError was thrown building UserProfile(dirty, state: _UserProfileState#c6357):
LateInitializationError: Field 'avatar' has not been initialized.
The relevant error-causing widget was:
UserProfile UserProfile:file:///C:/Users/Emman/AndroidStudioProjects/json_crud/lib/main.dart:28:19
When the exception was thrown, this was the stack:
#0 User.avatar (package:json_crud/classes/user.dart)
#1 _UserProfileState.build (package:json_crud/screens/user_profile.dart:81:19)
#2 StatefulElement.build (package:flutter/src/widgets/framework.dart:4705:27)
#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4588:15)
#4 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4763:11)
#5 Element.rebuild (package:flutter/src/widgets/framework.dart:4311:5)
#6 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4566:5)
#7 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4754:11)
#8 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4561:5)
... Normal element mounting (169 frames)
#177 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3631:14)
#178 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6261:36)
#179 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6272:32)
... Normal element mounting (391 frames)
#570 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3631:14)
#571 Element.updateChild (package:flutter/src/widgets/framework.dart:3383:18)
#572 RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1198:16)
#573 RenderObjectToWidgetElement.mount (package:flutter/src/widgets/binding.dart:1167:5)
#574 RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> (package:flutter/src/widgets/binding.dart:1112:18)
#575 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2531:19)
#576 RenderObjectToWidgetAdapter.attachToRenderTree (package:flutter/src/widgets/binding.dart:1111:13)
#577 WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:944:7)
#578 WidgetsBinding.scheduleAttachRootWidget.<anonymous closure> (package:flutter/src/widgets/binding.dart:924:7)
(elided 11 frames from class _RawReceivePortImpl, class _Timer, dart:async, and dart:async-patch)
====================================================================================================
how can i solve this
CodePudding user response:
It says where the error after your changes comes from right there:
type 'String?' is nullable and 'String' isn't.
so when you type your variable firstName like this: String? firstName; then the compiler is totally happy with firstName = null.
When you type it like String firstName; then its type "String" _prevents it from ever becoming null.
Maybe you have somewhere typed what should be a String? (or fetched by an if) as String, f.e. in
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);?
CodePudding user response:
You are calling getUser in your init method, but since it it's async and returns a Future, you need to await it. Otherwise your code will not have completed when your build method gets called and your variables are still set to their default values (which means your late variables have never been initialized on those instances and you get the error you see).
As you cannot use the await keyword in a method that is not itself async (and initState is not), you need to find a way around that. The most common is using a FutureBuilder widget.
You can find a good example of the general setup here: What is a Future and how do I use it?
