Home > front end >  Get data from async function inside ListView (without FutureBuilder)
Get data from async function inside ListView (without FutureBuilder)

Time:01-18

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);
              },
            );
          }),
  •  Tags:  
  • Related