Flutter — попытка отобразить список твитов, извлеченных из JSON, в ListView

#flutter #dart

Вопрос:

Я пытаюсь получить список твитов, используя HTTP-библиотеку Flutter и конечную точку API Twitter, а затем отобразить список твитов в виджете ListView, используя библиотеку Flutter tweet_ui. Мне удалось получить корректную выборку списка твитов, и я получаю ответ JSON. Однако в настоящее время я пытаюсь декодировать ответ JSON.тело и сохраните его в списке для последующего кодирования, как только я передам его используемому мной методу tweet_ui. Используя код, который я показал ниже, я продолжаю получать этот красный экран ошибки с сообщением об ошибке «Ожидалось значение типа ‘String’, но получено значение типа ‘_Future < dynamic>'». Я несколько раз пытался поиграть с различными типами, которые передаются от функции к функции, и это, похоже, не работает. Я также попытался обернуть виджет вокруг будущего конструктора, и это, похоже, не сработало. Есть идеи, что я мог делать неправильно?

 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;
}
 

Функция, используемая для извлечения твитов с использованием HTTP-библиотеки из Twitter API

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

tweets = convert.jsonDecode(jsonData);

return tweets;
}
 

Функция, используемая для преобразования каждого твита, извлеченного из Json, для добавления в список.

 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]),
                  ),
                )
              ],
            ));
          }),
    ),
  ]),
);
 

}

Виджет, использующий 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]),
                        ),
                      )
                    ],
                  ));
                });
          }
        },
      ),
    ),
  ),
);
 

}

Альтернативный виджет с использованием Future Builder

Ответ №1:

Я предлагаю

  1. Создайте модель класса для tweet
  2. Получите данные json из api, затем декодируйте их в json, после сопоставьте их с созданным классом, а затем преобразуйте в list (будущий конструктор возвращает список твитов) или, если вы используете управление состоянием (перейдите к шагу 4).
  3. Используйте управление состоянием ie. Поставщик или Getx

Следующее, если вы используете поставщика в качестве управления состоянием

  1. если ваш провайдер использует уведомление об изменении и сохраняет список твитов в виде списка типа данных, что-то вроде List<your_tweet_class> , и теперь вы можете получить к нему доступ Provider.of(context) с помощью указанного класса

Комментарии:

1. У вас есть пример пример будущего разработчика, возвращающего список твитов?

2. Я не уверен, что лучше всего создать модель класса для tweet, поскольку функция Tweet.fromRawJson() принимает строку, а библиотека tweet_ui уже поставляется с классом Tweet .