1

I'm trying to get the value from an Async function that returns an integer which is then used to set the color of a widget in my UI.

Async function:

// Returns a future<int> instead of an int due to async
Future<int> getLikeStatus(String name) async {
  int likeStatus =
      await getLikeStatusFromPostLikes(name); // this returns an int
  return likeStatus;
}

Post Function:

 Future <List<dynamic>> fetchData() async {
  // Some code to make GET request to private server with data and push as posts
  final response = await posts.get();
  final result = response.map((m) => Post.fromJson(m)).toList();

  return result;
}

Downstream usage - uses the above post function:

// snapshot is populated by post future in FutureBuilder
child: FutureBuilder<List<dynamic>>(
              future: post,
              builder: (context, snapshot) {
                if (snapshot.hasData) { 
                   ...
                   Row(
                      mainAxisSize: MainAxisSize.min,
                      children: <Widget>[
                         InkWell(
                            child: IconButton(
                            icon: Icon(Icons.thumb_up),
                            color: getLikeStatus(snapshot.data[index].name) == 1
                ? Colors.green
                : Colors.blue) // cannot use future here
                      ),
  ],
);

How can I return the likeStatus variable to use for the color attribute in my widget?

EDIT: Added code showing use of FutureBuilder

4
  • use FutureBuilder (api.flutter.dev/flutter/widgets/FutureBuilder-class.html) widget Commented Jan 20, 2020 at 15:38
  • @Black what did you assign to post variable? Commented Jan 20, 2020 at 16:44
  • @CrazyLazyCat made edit Commented Jan 20, 2020 at 16:49
  • @Black but you can still use the solution that creativecreatorormaybenot gave. Commented Jan 20, 2020 at 16:57

1 Answer 1

1

If you don't want to use nested FutureBuilder then you can make them as single future function(fetchAll) like this,

post = fetchAll();

....

Future<Map<Post, int>> fetchAll() async {
  final posts = await fetchData();
  final result = <Post, int>{};
  for(final x in posts){
    final status = await getLikeStatus(x.name);
    result[x] = status;
  }
  return result;
}

Future <List<Post>> fetchData() async {
  // Some code to make GET request to private server with data and push as posts
  final response = await posts.get();
  final result = response.map((m) => Post.fromJson(m)).toList();
  return result;
}

// Returns a future<int> instead of an int due to async
Future<int> getLikeStatus(String name) async {
  int likeStatus =
  await getLikeStatusFromPostLikes(name); // this returns an int
  return likeStatus;
}

...

    child: FutureBuilder<Map<Post, int>>(
      future: post,  //TODO: `fetchAll` instead of `fetchData`
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          //Since snapshot is a map you can get `Post` data using `snapshot.data.entries.elementAt(index)`
          ...
          Row(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              InkWell(
                  child: IconButton(
                      icon: Icon(Icons.thumb_up),
                      color: snapshot.data.entries.elementAt(index).value
                          ? Colors.green
                          : Colors.blue) // cannot use future here
              ),
            ],
          ),
          //...
        }
      },
    ),

Above the fetch status request send one after another. So it may take long if the name list is large. You can make it parallel like this,

Future<Map<Post, int>> fetchAll() async {
  final posts = await fetchData();
  final result = <Post, int>{};
  final statusList =
      await Future.wait<int>(posts.map((x) => getLikeStatus(x.name)));
  for (int i = 0; i < posts.length; i++) {
    result[posts[i]] = statusList[i];
  }
  return result;
}
Sign up to request clarification or add additional context in comments.

3 Comments

I didn't know multiple futures could be added into one super future. Thank you
@Black Don't use .forEach in fetchAll method. I updated the code
Changed this, optimisation makes a lot of sense. Thank you

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.