I'm making a simple app with Star Wars data and I keep getting snapshot data is null, the only thing that comes to mind is that I'm not populating the model correctly and I can't seem to find the solution to this problem. The code:
Model:
class PeopleModel {
String? name;
String? height;
String? mass;
String? hairColor;
String? skinColor;
String? eyeColor;
String? birthYear;
String? gender;
String? homeworld;
List<String>? films;
List<String>? species;
List<String>? vehicles;
List<String>? starships;
String? created;
String? edited;
String? url;
PeopleModel(
{this.name,
this.height,
this.mass,
this.hairColor,
this.skinColor,
this.eyeColor,
this.birthYear,
this.gender,
this.homeworld,
this.films,
this.species,
this.vehicles,
this.starships,
this.created,
this.edited,
this.url});
PeopleModel.fromJson(Map<String, dynamic> json) {
name = json['name'];
height = json['height'];
mass = json['mass'];
hairColor = json['hair_color'];
skinColor = json['skin_color'];
eyeColor = json['eye_color'];
birthYear = json['birth_year'];
gender = json['gender'];
homeworld = json['homeworld'];
films = json['films'].cast<String>();
species = json['species'].cast<String>();
vehicles = json['vehicles'].cast<String>();
starships = json['starships'].cast<String>();
created = json['created'];
edited = json['edited'];
url = json['url'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['name'] = name;
data['height'] = height;
data['mass'] = mass;
data['hair_color'] = hairColor;
data['skin_color'] = skinColor;
data['eye_color'] = eyeColor;
data['birth_year'] = birthYear;
data['gender'] = gender;
data['homeworld'] = homeworld;
data['films'] = films;
data['species'] = species;
data['vehicles'] = vehicles;
data['starships'] = starships;
data['created'] = created;
data['edited'] = edited;
data['url'] = url;
return data;
}
}
Store for the provider model:
import 'package:flutter/foundation.dart';
class PeopleStore extends ChangeNotifier {
bool _loading = false;
Map<String?, PeopleModel> _people = {};
bool getLoading() => _loading;
void setLoading(bool loading) {
_loading = loading;
notifyListeners();
}
void setPeople(Map<String?, PeopleModel> people) {
_people = people;
notifyListeners();
}
Map<String?, PeopleModel>? getPeople() => _people;
}
The Api call:
Future<HTTPResponse<Map<String?, PeopleModel>>> getPeople() async {
final response = await (SWHttpProvider.apiRequest(Method.GET, 'people'));
dynamic body = jsonDecode(utf8.decode(response!.bodyBytes));
if (response.statusCode == 200) {
dynamic data = body['results'] as List?;
Map<String?, PeopleModel> peopleMap = {};
data.forEach((peopleData) {
PeopleModel people = PeopleModel.fromJson(peopleData);
peopleMap[people.name] = people ;
});
return HTTPResponse<Map<String?, PeopleModel>>(
isSuccessful: true,
data: peopleMap,
message: HTTPResponse.successMessage,
statusCode: response.statusCode,
);
} else {
return HTTPResponse<Map<String?, PeopleModel>>(
isSuccessful: false,
data: null,
message: body['message'] ?? HTTPResponse.errorMessage,
statusCode: response.statusCode,
);
}
}
The API JSON data:
https://swapi.dev/api/people/ /// the URL for the API
{
"count": 82,
"next": "https://swapi.dev/api/people/?page=2",
"previous": null,
"results": [
{
"name": "Luke Skywalker",
"height": "172",
"mass": "77",
"hair_color": "blond",
"skin_color": "fair",
"eye_color": "blue",
"birth_year": "19BBY",
"gender": "male",
"homeworld": "https://swapi.dev/api/planets/1/",
"films": [
"https://swapi.dev/api/films/1/",
"https://swapi.dev/api/films/2/",
"https://swapi.dev/api/films/3/",
"https://swapi.dev/api/films/6/"
],
"species": [],
"vehicles": [
"https://swapi.dev/api/vehicles/14/",
"https://swapi.dev/api/vehicles/30/"
],
"starships": [
"https://swapi.dev/api/starships/12/",
"https://swapi.dev/api/starships/22/"
],
"created": "2014-12-09T13:50:51.644000Z",
"edited": "2014-12-20T21:17:56.891000Z",
"url": "https://swapi.dev/api/people/1/"
},
{
"name": "C-3PO",
"height": "167",
"mass": "75",
"hair_color": "n/a",
"skin_color": "gold",
"eye_color": "yellow",
"birth_year": "112BBY",
"gender": "n/a",
"homeworld": "https://swapi.dev/api/planets/1/",
"films": [
"https://swapi.dev/api/films/1/",
"https://swapi.dev/api/films/2/",
"https://swapi.dev/api/films/3/",
"https://swapi.dev/api/films/4/",
"https://swapi.dev/api/films/5/",
"https://swapi.dev/api/films/6/"
],
"species": [
"https://swapi.dev/api/species/2/"
],
"vehicles": [],
"starships": [],
"created": "2014-12-10T15:10:51.357000Z",
"edited": "2014-12-20T21:17:50.309000Z",
"url": "https://swapi.dev/api/people/2/"
},
{
"name": "R2-D2",
"height": "96",
"mass": "32",
"hair_color": "n/a",
"skin_color": "white, blue",
"eye_color": "red",
"birth_year": "33BBY",
"gender": "n/a",
"homeworld": "https://swapi.dev/api/planets/8/",
"films": [
"https://swapi.dev/api/films/1/",
"https://swapi.dev/api/films/2/",
"https://swapi.dev/api/films/3/",
"https://swapi.dev/api/films/4/",
"https://swapi.dev/api/films/5/",
"https://swapi.dev/api/films/6/"
],
"species": [
"https://swapi.dev/api/species/2/"
],
"vehicles": [],
"starships": [],
"created": "2014-12-10T15:11:50.376000Z",
"edited": "2014-12-20T21:17:50.311000Z",
"url": "https://swapi.dev/api/people/3/"
},
{
"name": "Darth Vader",
"height": "202",
"mass": "136",
"hair_color": "none",
"skin_color": "white",
"eye_color": "yellow",
"birth_year": "41.9BBY",
"gender": "male",
"homeworld": "https://swapi.dev/api/planets/1/",
"films": [
"https://swapi.dev/api/films/1/",
"https://swapi.dev/api/films/2/",
"https://swapi.dev/api/films/3/",
"https://swapi.dev/api/films/6/"
],
"species": [],
"vehicles": [],
"starships": [
"https://swapi.dev/api/starships/13/"
],
"created": "2014-12-10T15:18:20.704000Z",
"edited": "2014-12-20T21:17:50.313000Z",
"url": "https://swapi.dev/api/people/4/"
},
{
"name": "Leia Organa",
"height": "150",
"mass": "49",
"hair_color": "brown",
"skin_color": "light",
"eye_color": "brown",
"birth_year": "19BBY",
"gender": "female",
"homeworld": "https://swapi.dev/api/planets/2/",
"films": [
"https://swapi.dev/api/films/1/",
"https://swapi.dev/api/films/2/",
"https://swapi.dev/api/films/3/",
"https://swapi.dev/api/films/6/"
],
"species": [],
"vehicles": [
"https://swapi.dev/api/vehicles/30/"
],
"starships": [],
"created": "2014-12-10T15:20:09.791000Z",
"edited": "2014-12-20T21:17:50.315000Z",
"url": "https://swapi.dev/api/people/5/"
},
{
"name": "Owen Lars",
"height": "178",
"mass": "120",
"hair_color": "brown, grey",
"skin_color": "light",
"eye_color": "blue",
"birth_year": "52BBY",
"gender": "male",
"homeworld": "https://swapi.dev/api/planets/1/",
"films": [
"https://swapi.dev/api/films/1/",
"https://swapi.dev/api/films/5/",
"https://swapi.dev/api/films/6/"
],
"species": [],
"vehicles": [],
"starships": [],
"created": "2014-12-10T15:52:14.024000Z",
"edited": "2014-12-20T21:17:50.317000Z",
"url": "https://swapi.dev/api/people/6/"
},
{
"name": "Beru Whitesun lars",
"height": "165",
"mass": "75",
"hair_color": "brown",
"skin_color": "light",
"eye_color": "blue",
"birth_year": "47BBY",
"gender": "female",
"homeworld": "https://swapi.dev/api/planets/1/",
"films": [
"https://swapi.dev/api/films/1/",
"https://swapi.dev/api/films/5/",
"https://swapi.dev/api/films/6/"
],
"species": [],
"vehicles": [],
"starships": [],
"created": "2014-12-10T15:53:41.121000Z",
"edited": "2014-12-20T21:17:50.319000Z",
"url": "https://swapi.dev/api/people/7/"
},
{
"name": "R5-D4",
"height": "97",
"mass": "32",
"hair_color": "n/a",
"skin_color": "white, red",
"eye_color": "red",
"birth_year": "unknown",
"gender": "n/a",
"homeworld": "https://swapi.dev/api/planets/1/",
"films": [
"https://swapi.dev/api/films/1/"
],
"species": [
"https://swapi.dev/api/species/2/"
],
"vehicles": [],
"starships": [],
"created": "2014-12-10T15:57:50.959000Z",
"edited": "2014-12-20T21:17:50.321000Z",
"url": "https://swapi.dev/api/people/8/"
},
{
"name": "Biggs Darklighter",
"height": "183",
"mass": "84",
"hair_color": "black",
"skin_color": "light",
"eye_color": "brown",
"birth_year": "24BBY",
"gender": "male",
"homeworld": "https://swapi.dev/api/planets/1/",
"films": [
"https://swapi.dev/api/films/1/"
],
"species": [],
"vehicles": [],
"starships": [
"https://swapi.dev/api/starships/12/"
],
"created": "2014-12-10T15:59:50.509000Z",
"edited": "2014-12-20T21:17:50.323000Z",
"url": "https://swapi.dev/api/people/9/"
},
{
"name": "Obi-Wan Kenobi",
"height": "182",
"mass": "77",
"hair_color": "auburn, white",
"skin_color": "fair",
"eye_color": "blue-gray",
"birth_year": "57BBY",
"gender": "male",
"homeworld": "https://swapi.dev/api/planets/20/",
"films": [
"https://swapi.dev/api/films/1/",
"https://swapi.dev/api/films/2/",
"https://swapi.dev/api/films/3/",
"https://swapi.dev/api/films/4/",
"https://swapi.dev/api/films/5/",
"https://swapi.dev/api/films/6/"
],
"species": [],
"vehicles": [
"https://swapi.dev/api/vehicles/38/"
],
"starships": [
"https://swapi.dev/api/starships/48/",
"https://swapi.dev/api/starships/59/",
"https://swapi.dev/api/starships/64/",
"https://swapi.dev/api/starships/65/",
"https://swapi.dev/api/starships/74/"
],
"created": "2014-12-10T16:16:29.192000Z",
"edited": "2014-12-20T21:17:50.325000Z",
"url": "https://swapi.dev/api/people/10/"
}
]
}
Actions providing the data to the model:
Future<void> fetchPeople() async {
final peopleRes = await peopleApi.getPeople();
if (peopleRes.isSuccessful!) {
peopleStore.setPeople(peopleRes.data!);
}
}
The returning data from the FutureBuilder is always 'Empty Data':
FutureBuilder(
future: PeopleActions(context).fetchPeople(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
} else if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return const Text('Error');
} else if (snapshot.hasData) {
return ListView.builder(
itemCount: 5,
itemBuilder: (BuildContext context, int index) {
final data =
Provider.of<PeopleStore>(context, listen: false)
.getPeople();
return Text('${data![index]?.name} $index');
});
} else {
return const Text('Empty data');
}
} else {
return Text('State: ${snapshot.connectionState}');
}
},
),
Thanks in advance for your help!
CodePudding user response:
You need to return something in your FutureBuilder's future
in order to snapshot has data, so change your fetchPeople()
to this:
Future<Map<String?, PeopleModel>> fetchPeople() async {
final peopleRes = await peopleApi.getPeople();
if (peopleRes.isSuccessful!) {
peopleStore.setPeople(peopleRes.data!);
return peopleRes.data!;
}else {
return {};
}
}