Невозможно обновить список после получения Json

Я пытался получить данные с сервера и отобразить их в listview.builder внутри futurebuilder, но список обновляется только после применения setstate (), пожалуйста, помогите застрять на некоторое время.

  Future<dynamic> _fetchData() async {
    sPref.getUserId().then((onValue) {
      userIds = onValue;
    });
    sPref.getAuthToken().then((val) {
      token = val;
      var body = {
        'userId': '$userIds',
      };
      var client = http.Client();    

      var response = http.Request(
          'POST', Uri.parse('http://example.net/api/fetchJson'));    

      response.headers["Authorization"] = "Bearer $token";
      response.bodyFields = body;
      print(response.headers);
      client.send(response).then((response) {
        return http.Response.fromStream(response);
      }).then((res) {
        return res.body;
      }).then((body) {
        return json.decode(body);
      }).then((body) {
        print(body.toString());
        var datas = body['data'];
        if (body['status'] == 'success') {
          list = (datas as List)
              .map((data) => new PosModelData.fromJson(data))
              .toList();
          return list;
        } else {
          print('failed');
        }
      });
      return list;
    });
  }  

Именно сюда я и буду звонить в будущем. Мне нужно знать, в чем я ошибаюсь.

           body: FutureBuilder(
             future: _fetchData(),
             builder: (context, data) {
               switch (data.connectionState) {
                 case ConnectionState.none:
                 case ConnectionState.waiting:
                   return Center(child: CircularProgressIndicator());
                 default:
                   // if (data.hasError)
                   //   return new Text('Error: ${data.error}');
                   // else
                   return ListView.builder(
                     itemCount: list.length,
                     itemBuilder: (BuildContext context, int index) {
                       return Container(
                         padding: EdgeInsets.symmetric(
                             horizontal: 6.0, vertical: 4.0),
                         child: Card(
                           elevation: 10.0,
                           child: Column(children: <Widget>[
                             ListTile(
                               title: Text(list[index].firstName),
                               subtitle: list[index].phone != null
                                   ? Text(list[index].phone)
                                   : Text('Not mentioned'),
                               trailing: trailingText(index),
                             ),
                           ]),
                         ),
1
0
137
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В вашем коде вы не вызывали return из своего блока _fetchData().

Ваш тип возврата - Future, вам нужно использовать await, укажите свой тип возврата List<PosModelData> и return из вашего блока async

Future<List<PosModelData>> _fetchData() async {
  final response = await http.Request('POST', Uri.parse('http://example.net/api/fetchJson')); 
  final list = ... convert response to list
  return list;
}

Затем вы получите список от обратного вызова builder: (context, data) {}.

Пожалуйста, проверьте пример это.

Обновлено 1

Вместо использования async и await можно использовать другой способ использования Future - вернуть тип Future. Укажите тип возврата Future<List< PosModelData>> и верните тип Future

return sPref.then((s) {}.

Пожалуйста, проверьте следующие примеры кодов и Futuresдокумент для асинхронного программирования dart.

Future<List<PosModelData>> _fetchData() {
  return Future.wait([sPref.getUserId(), sPref.getAuthToken()]).then((data) {
    userIds = data.first;
    token = data[1];

    var body = {
      'userId': '$userIds',
    };
    var client = http.Client();

    var response = http.Request(
        'POST', Uri.parse('http://example.net/api/fetchJson'));

    response.headers["Authorization"] = "Bearer $token";
    response.bodyFields = body;
    print(response.headers);
    return client.send(response).then((response) {
      return http.Response.fromStream(response);
    }).then((res) {
      return res.body;
    }).then((body) {
      return json.decode(body);
    }).then((body) {
      print(body.toString());
      var datas = body['data'];
      if (body['status'] == 'success') {
        list = (datas as List)
            .map((data) => new PosModelData.fromJson(data))
            .toList();
        return list;
      } else {
        print('failed');
      }
    });
  });

Я попытался добавить реализацию await bt внутри sPref.getAuthtoken не работает.

rahul.sharma 24.10.2018 06:51

это может сработать, но sPref или экземпляр sharedPreference не имеют метода ".then"

rahul.sharma 25.10.2018 12:12

пожалуйста, проверьте обновленную часть. Вы можете использовать Future.wait для объединения тех экземпляров, которые имеют метод .then, например sPref.getUserId() и sPref.getAuthToken().

Joseph Cheng 25.10.2018 18:34

классное братан, спасибо, это сработало, и я узнал что-то новое :)

rahul.sharma 26.10.2018 11:19

Другие вопросы по теме