My app's home page uses a ListView.builder
to create a feed of posts. Each post has to show the owner's profile picture as well as other data. In the ListView.builder
I call a function to get the profile picture URL from Firebase
like this:
ListView.builder(
itemCount: listPosts.length,
itemBuilder: (BuildContext context, int index) {
// We retrieve the post at index « index »
final post = listPosts[index];
// Get name from id
var parts = post.id.split('_');
var username = parts[0].trim();
// Get pfpUrl
String pfpUrlString = pfpUrl(username);
return _buildPost(
username, post.postUrlString, post.caption, pfpUrlString);
}),
The ```pfpUrl(username)''' function that I call looks like this and returns the URL as a string:
pfpUrl(String username) async {
// Get pfpUrl
String pfpUrlString = await FirebaseStorage.instance
.ref()
.child("$username/profile_picture.png")
.getDownloadURL();
return pfpUrlString;
}
So the function returns the String but I can't call it using await
inside the ListView.builder
because it's not an async function. I can't use a FutureBuilder
because the username comes from the post id which I can only get inside the ListView.Builder
. Instead of returning a value, I tried making a global variable and setting it to each URL in the function, then setting that variable as the URL in the builder. That doesn't work because it ends up putting random profile pictures on each post. Can someone please give me solution ideas?
CodePudding user response:
You can use this widget to load and display profile photo from username. Use like this in your _buildPost method.:
ProfileImageWidget('username')
class ProfileImageWidget extends StatelessWidget {
final username;
ProfileImageWidget(this.username){
getUrl = FirebaseStorage.instance
.ref()
.child("$username/profile_picture.png")
.getDownloadURL();
}
late Future<String> getUrl;
@override
Widget build(BuildContext context) {
return FutureBuilder<String>(
future: getUrl,
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if(!snapshot.hasData) return Text('getting profile url');
return Image.network(snapshot.data!);
});
}
}
CodePudding user response:
You could just return a FutureBuilder where you get your Image Url and then return in this your _buildPost
Try it like this:
ListView.builder(
itemCount: listPosts.length,
itemBuilder: (BuildContext context, int index) {
// We retrieve the post at index « index »
final post = listPosts[index];
// Get name from id
var parts = post.id.split('_');
var username = parts[0].trim();
// Get pfpUrl
String pfpUrlString = pfpUrl(username);
return FutureBuilder(
future: <your future to get the image Url>,
builder: (BuildContext context, AsyncSnapshot snapshot){
return _buildPost(
username, post.postUrlString, post.caption, pfpUrlString);
},
);
}),