'Flutter - Attempting to display a list of tweets fetched from JSON onto ListView

I am attempting to fetch a list of tweets using Flutter's HTTP library and Twitter's API endpoint, and then display the list of tweets onto a ListView widget using a Flutter tweet_ui library. I was able to get the fetching of a list of tweets working correctly and I get back a JSON response. However, I am currently attempting to decode the JSON response.body and save it onto a List to later encode once I pass it to the tweet_ui method I am using. Using the code I've shown below I continue get this red error screen with the error saying "Expected a value of type 'String', but got one of type '_Future < dynamic >'". I've tried multiple times playing around with the different types that are being passed around from function to function and that does not seem to work. I've also attempted to wrap the widget around a future builder, and that did not seem to work as well. Any idea what I could possibly be doing wrong?

Future getTweetJson() async {
Map<String, String> params = {
  'exclude': 'retweets',
  'expansions':
      'attachments.poll_ids,attachments.media_keys,author_id,entities.mentions.username,geo.place_id,in_reply_to_user_id,referenced_tweets.id,referenced_tweets.id.author_id',
  'tweet.fields':
      'attachments,author_id,context_annotations,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang,possibly_sensitive,public_metrics,reply_settings,source,text',
  'user.fields':
      'created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified',
  'place.fields':
      'contained_within,country,country_code,full_name,geo,id,name,place_type',
  'media.fields':
      'duration_ms,height,media_key,preview_image_url,type,url,width,public_metrics,non_public_metrics,organic_metrics,promoted_metrics'
};

var response = await http.get(
    Uri.https('api.twitter.com', '2/users/IDnumber/tweets', params),
    headers: {
      "Authorization":
          "Bearer bearerToken"
    });

String jsonData = response.body;   

return jsonData;
}

Function used to fetch tweets using HTTP library from Twitter API

List getListOfTweets(var jsonData) {
List<dynamic> tweets = [];

tweets = convert.jsonDecode(jsonData);

return tweets;
}

Function used to hopefully convert each tweet fetched in the Json to be added to the list.

List<dynamic> tweets = handler.getListOfTweets(handler.getTweetJson());

@override
Widget build(BuildContext context) {
return Scaffold(
  appBar: AppBar(title: Text("Tweets")),
  body: Column(children: <Widget>[
    Expanded(
      child: ListView.builder(
          itemCount: tweets.length,
          itemBuilder: (context, index) {
            return Container(
                child: Column(
              children: [
                EmbeddedTweetView.fromTweet(
                  Tweet.fromRawJson(
                    convert.jsonEncode(tweets[index]),
                  ),
                )
              ],
            ));
          }),
    ),
  ]),
);

}

Widget using ListView

var tweetJson = handler.getTweetJson();

@override
Widget build(BuildContext context) {
return Scaffold(
  appBar: AppBar(title: Text("Tweets")),
  body: Container(
    child: Card(
      child: FutureBuilder(
        future: tweetJson,
        builder: (context, AsyncSnapshot snapshot) {
          if (snapshot.data == null) {
            return Container(
              child: const Center(
                child: Text('Loading. . .'),
              ),
            );
          } else {
            var tweets =
                List<String>.from(convert.jsonDecode(snapshot.data));
            return ListView.builder(
                itemCount: tweets.length,
                itemBuilder: (context, index) {
                  return Container(
                      child: Column(
                    children: [
                      EmbeddedTweetView.fromTweet(
                        Tweet.fromRawJson(
                          convert.jsonEncode(tweets[index]),
                        ),
                      )
                    ],
                  ));
                });
          }
        },
      ),
    ),
  ),
);

}

Alternative Widget using Future Builder



Solution 1:[1]

I suggest to

  1. Create a class model for tweet

  2. Get the json data from api then decode it to json ,after map it to the created class and then convert it to list (A future builder returning a list of tweets) or if you use state management (skip to step 4).

  3. Use a state management ie. Provider or Getx

The following is if you use provider as state management

  1. if your using provider use change notifier and save the list of tweets to a list datatype something like List<your_tweet_class> and now you can access it using Provider.of(context) with the class specified

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Saffron-codes