I'm currently coding a project with front-end in Flutter Dart, and back-end in JSON. I am trying to pull profile data entered by the user to display in the settings via a FutureBuilder, but every time even though I can view the profile data in the log, it keeps returning as a null value in Flutter. Any suggestions ? Thanks :)
import 'package:json_annotation/json_annotation.dart';
part 'profile_model.g.dart';
@JsonSerializable(explicitToJson: true)
class ProfileModel {
String? firstname;
String? lastname;
String? birthday;
String? weight;
ProfileModel({this.firstname, this.lastname, this.birthday, this.weight});
factory ProfileModel.fromJson(Map<String,dynamic> json) => _$ProfileModelFromJson(json);
Map<String,dynamic> toJson() => _$ProfileModelToJson(this);
}
class SettingsProfile extends StatefulWidget {
const SettingsProfile({Key? key}) : super(key: key);
@override
_SettingsProfileState createState() => _SettingsProfileState();}
class _SettingsProfileState extends State<SettingsProfile> {
final _formKey = GlobalKey<FormState>();
final networkHandler = NetworkHandler();
bool circular = true;
Widget page = CircularProgressIndicator();
@override
void initState() {super.initState(); checkProfile();}
void checkProfile() async {
var response = await networkHandler.get('/profile/checkProfile');
if (response['status'] == true) {setState(() {page = showProfile();});}
else {setState(() {page = emptyProfile();});}}
TextEditingController firstnameController = TextEditingController();
TextEditingController lastnameController = TextEditingController();
TextEditingController birthdayController = TextEditingController();
TextEditingController weightController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Mon profil')),
body: page,);}
Future<ProfileModel> _loadProfileModel() async {
var response = await networkHandler.get("/profile/getData");
setState(() {ProfileModel profileModel = ProfileModel.fromJson(response["data"]);});
return response;}
Widget showProfile() {
return FutureBuilder<ProfileModel>(
future: _loadProfileModel(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data == null) {
return Text('no data');
} else {
print((snapshot.data()! as Map<String, dynamic>)['firstname'] as String);
return Text('data present');
}
} else if (snapshot.connectionState == ConnectionState.waiting) {
return Text('Error'); // error
} else {
return CircularProgressIndicator(); // loading
}
}
);
/*
return Scaffold(
body: FutureBuilder(
future: _loadProfileModel(),
builder: (context, data) {
if (data.hasError) {
return Center(child: Text("${data.error}"));
} else if (data.hasData) {
return Card(
elevation: 5,
margin: EdgeInsets.symmetric(horizontal: 10, vertical: 6),
child: Container(
padding: EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Container(
padding: EdgeInsets.only(bottom: 8),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(left: 8, right: 8),
child: Text(
profileModel.firstname.toString(),
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold),
),
),
Padding(
padding: EdgeInsets.only(left: 8, right: 8),
child: Text(profileModel.lastname.toString()),
)
],
),
))
],
),
),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
)
);
*/
/*
void fetchData() async {
var response = await networkHandler.get("/profile/getData");
setState(() {
ProfileModel profileModel = ProfileModel.fromJson(response["data"]);
});
}
fetchData();
return Text(profileModel.firstname.toUpperCase());
*/
}
Widget emptyProfile() {
// GOOD CODE
}
}
Edit : added this next block of code to simplify the one right above
class _SettingsProfileState extends State<SettingsProfile> {
final _formKey = GlobalKey<FormState>();
final networkHandler = NetworkHandler();
ProfileModel profileModel = ProfileModel();
bool circular = true;
TextEditingController firstnameController = TextEditingController();
TextEditingController lastnameController = TextEditingController();
TextEditingController birthdayController = TextEditingController();
TextEditingController weightController = TextEditingController();
Widget page = CircularProgressIndicator();
@override
void initState() {super.initState(); checkProfile(); fetchData();}
void checkProfile() async {
var response = await networkHandler.get('/profile/checkProfile');
if (response['status'] == true) {setState(() {
page = showProfile();
});}
else {setState(() {page = emptyProfile();});}}
void fetchData() async {
var foundDetails = await networkHandler.get("/profile/getData");
setState(() {
ProfileModel profileModel = ProfileModel.fromJson(foundDetails);
circular = false;});}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Mon profil')),
body: page,);}
Widget showProfile() {
return Container(
child: Text(
profileModel.weight.toString(),
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),),);}
CodePudding user response:
Try this:
void fetchData() async {
var foundDetails = await networkHandler.get("/profile/getData");
setState(() {
/*ProfileModel*/ profileModel = ProfileModel.fromJson(foundDetails);
circular = false;});}
CodePudding user response:
Future<ProfileModel> _loadProfileModel() async {
var response = await networkHandler.get("/profile/getData");
setState(() {ProfileModel profileModel = ProfileModel.fromJson(response["data"]);});
return response;}
What does this method do? it is supposed to return a ProfileModel
but instead, it returns the API response, plus, your are declaring a variable inside the setState
, this means that it's scope is only that setState
method.
your method should be:
Future<ProfileModel> _loadProfileModel() async {
var response = await networkHandler.get("/profile/getData");
return ProfileModel.fromJson(response["data"]);
}