I'm trying to return ListView of photos via FutureBuilder fetched with data from API. While values are added to List in my service and assigned properly, values fetched to List Builder are null. I don't know why calling service method to return Future<List> returns list of null.
My model:
class Photo {
String id;
String photoDesc;
String photoAuthor;
String photoUrlSmall;
String photoUrlFull;
String downloadUrl;
int likes;
Photo(
{this.id,
this.photoDesc,
this.photoAuthor,
this.photoUrlSmall,
this.photoUrlFull,
this.downloadUrl,
this.likes});
Photo.fromJson(Map<String, dynamic> json) {
id = json['id'];
photoDesc = json['description'] != null
? json['description']
: json['alt_description'];
photoAuthor = json['user']['name'] != null
? json['user']['name']
: json['user']['username'];
photoUrlSmall = json['urls']['small'];
photoUrlFull = json['urls']['full'];
downloadUrl = json['links']['download'];
likes = json['likes'];
}
}
My service:
Future<List<Photo>> getRandomData1() async {
List<Photo> randomPhotos;
_response = await http.get(Uri.parse(
'$unsplashUrl/photos/random/?client_id=${_key.accessKey}&count=30'));
if (_response.statusCode == 200) {
return randomPhotos = (json.decode(_response.body) as List).map((i) {
Photo.fromJson(i);
print(Photo.fromJson(i).id); // **i.e. printing returns proper values**
}).toList();
} else {
print(_response.statusCode);
throw 'Problem with the get request';
}
}
My builder:
class RandomPhotosListView extends StatefulWidget {
@override
_RandomPhotosListViewState createState() => _RandomPhotosListViewState();
}
class _RandomPhotosListViewState extends State<RandomPhotosListView> {
final UnsplashApiClient unsplashApiClient = UnsplashApiClient();
Future _data;
ListView _randomPhotosListView(data) {
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return Text("${data[index]}");
});
}
@override
void initState() {
super.initState();
_data = unsplashApiClient.getRandomData1();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _data,
builder: (context, snapshot) {
print(snapshot.data); // i.e. snapshot.data here is list of nulls
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
print(snapshot.error);
return Text("error: ${snapshot.error}");
} else if (snapshot.hasData) {
return _randomPhotosListView(snapshot.data);
}
return Center(child: CircularProgressIndicator());
},
);
}
}
The reason you are having this issue is because you need to return the parsed object in your mapping function.
Solution #1 - add the return
keyword to your existing code
return randomPhotos = (json.decode(_response.body) as List).map((i) {
return Photo.fromJson(i); // <-- added return keyword here
}).toList();
Solution #2 - Use Arrow to define the return
This solution suits your code since you aren't manipulating the Photo object or any other data within the mapping.
return randomPhotos = (json.decode(_response.body) as List).map((i) => Photo.fromJson(i)).toList();
Either solution should work. Choose what suits your coding style and your needs.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.