Цепные асин c методы не показывают результат в виджете с FutureBuilder - PullRequest
0 голосов
/ 23 марта 2020

У меня проблема с отображением асинхронных данных в текстовом виджете.

Я выполняю два цепных асинхронных метода для поиска координат, а затем поиска города со смартфона:

Future<String> _getCity() async {
  Future<Position> pos = Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.low);
  String city = "";

  pos.then((result) {
    return result;
  })
  .then((result) async {
    List<Placemark> listPlacemark = await Geolocator().placemarkFromPosition(result);
    return listPlacemark;
  })
  .then((result) {
    return result.first;
  })
  .then((result) {
    city = result.subAdministrativeArea;
    // print( city ); -> Here it's showing correct data in console
  });

  return city;
}

Город отображается на консоли в этой закомментированной команде печати. ​​

Чтобы заполнить текстовый виджет, я делаю это:

Padding(
  padding: EdgeInsets.all(12),
  child: FutureBuilder<String>(
    future: _getCity(), // a Future<String> or null
    builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
      switch (snapshot.connectionState) {
        case ConnectionState.none:
          return Text('Error loading location');
        case ConnectionState.waiting:
          return Text('Waiting...');
        default:
          if (snapshot.hasError) {
            return Text('Error loading location');
          } else {
            return Text(snapshot.data);
          }
      }
    },
  ),
),

Я вызвал метод _getCity внутри метода initState, и это тоже сработало. Сообщение ожидания уже появилось, но теперь все пусто, чего не хватает?

Благодарю за внимание!

1 Ответ

1 голос
/ 24 марта 2020

Даже если вы возвращаете значение из обратного вызова then(), значение не возвращается из _getCity(). Вам нужно вернуть Future.

Future<String> _getCity() async {
  Future<Position> pos = Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.low);

  return pos.then((result) {
    return result;
  }).then((result) async {
    List<Placemark> listPlacemark = await Geolocator().placemarkFromPosition(result);
    return listPlacemark;
  }).then((result) {
    return result.first;
  }).then((result) {
    return result.subAdministrativeArea;
  });
}

Кстати, вам нужно так много then с?

Я никогда не использовал Geolocator(), поэтому это всего лишь предположение, но некоторые из них могут быть удалены, поскольку похоже, что listPlacemark, result.first и result.subAdministrativeArea не являются Future, и вы просто хотите извлечь значение из List<Position>. Если мое предположение верно, то подойдет следующее.

Future<String> _getCity() async {
  Future<Position> pos = Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.low);

  return pos.then((result) async {
    List<Placemark> listPlacemark = await Geolocator().placemarkFromPosition(result);
    return listPlacemark.first.subAdministrativeArea;
  });
}
...