#firebase #flutter #google-cloud-firestore #stream-builder
#firebase #flutter #google-облако-firestore #stream-builder
Вопрос:
Я использую StreamBuilder внутри метода сборки для извлечения информации о пользователе из firestore и сразу после ее отображения в Listview.builder.
Как только я получу информацию о пользователе, я вызываю другой API с идентификатором пользователя, чтобы получить некоторую другую информацию, которую я хотел бы отобразить в списке. Это дает мне будущее для каждого пользователя, как только будущее будет «выполнено» (внутри Future.then()), затем я сохраняю данные и вызываю setState(); чтобы перестроить список с новыми данными.
Проблема в том, что после вызова setState() метод сборки перезапускается, что снова возвращает мне пользователей, и это вызывает бесконечный цикл извлечения пользователей и данных из второго API.
Это похоже на типичный сценарий, но я не знаю, как решить это с помощью StreamBuilder. Мое предыдущее решение извлекало пользователей из initState, поэтому оно не вызывалось бесконечно. Какие-либо советы?
«getotherapeidata» перебирает извлеченных пользователей и добавляет данные «расстояние» в список, и список сортируется на основе пользователя с наибольшим / наименьшим расстоянием. Код:
@override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<List<IsFriend>>(
stream: viewModel.isFriendStream(),
builder: (_, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
List<IsFriend> friends = snapshot.data;
if (friends == null || friends.isEmpty) {
return Scaffold(
body: Center(
child: Text("Friend list is empty :("),
)
);
} else {
userList = friends;
getOtherAPIData();
return getListview(userList);
}
}
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
)
);
}
),
..
..
void getOtherAPIData() async {
for (IsFriend friend in userList) {
await fitbitServ.getData(friend.user.uid).then((fitData) {
setState(() {
setDistanceOnUser(fitData.distanceKm, friend.user.uid);
totalDistance = fitData.distanceKm;
sortUsers(userDataList);
userData[friend.user.uid] = fitData;
});
});
}
}
Ответ №1:
Вы никогда не должны вызывать метод, который начинает загрузку данных из вашего build
метода. Обычный поток, который я использую, это:
- Начните загрузку данных в конструктор виджета.
- Вызывайте
setState
, когда данные будут доступны. - Визуализируйте данные из состояния в
build
.
Комментарии:
1. Итак, решение состоит в том, чтобы не использовать StreamBuilder в подобных случаях? Я не понимаю, как я мог бы использовать ваш подход в этом сценарии, поскольку извлечение моих данных зависит от данных из StreamBuilder (которые, конечно, находятся внутри build() )
2. Использование a
StreamBuilder
тоже прекрасно, но затем вы не можете начать загрузку данных, которые он отображает в своем собственномbuilder
теле. Вложенные компоновщики — это нормально, но как только компоновщик запускает загрузку собственных данных в свойbuilder
метод, вы запускаете цикл, как вы видите.