#list #flutter #google-cloud-firestore
#Список #flutter #google-облако-firestore
Вопрос:
Я хотел бы добавить элемент в список:
void submitAll() async {
List<UserSearchItem> userSearchItems = [];
Firestore.instance
.collection('insta_users')
.snapshots()
.listen((data) =>
data.documents.forEach((doc){
print(data.documents.length);
User user = new User.fromDocument(doc);
UserSearchItem searchItem = new UserSearchItem(user);
userSearchItems.add(searchItem);
print(user.bio);
}));
print("Loaded");
print(userSearchItems.length);
}
Но если я выведу длину списка на консоль, там всегда будет указано, что длина списка равна 0…
print(userSearchItems.length);
Есть предложения?
С наилучшими пожеланиями
Комментарии:
1. Помогает ли использование
setState(() {});
вокруг `userSearchItems.add(…)’?2. Нет, это не работает.
Ответ №1:
Я попытаюсь дать объяснение того, что здесь происходит, взгляните на этот код:
import 'dart:async';
void main() {
List<int> userSearchItems = [];
Timer _sendTimeOutTimer;
const oneSec = Duration(seconds: 2);
_sendTimeOutTimer = Timer.periodic(oneSec, (Timer t) {
userSearchItems.add(1);
print(userSearchItems.length); // result 1 and it will be executed after 2 seconds
_sendTimeOutTimer.cancel();
});
print(userSearchItems.length); // result 0 and it will be executed first
}
Печать внутри асинхронного действия (Timer), которое будет выполнено через 2 секунды, означает, что после завершения асинхронного действия, но того, которое находится за пределами асинхронного действия (Timer), оно будет выполнено напрямую, не дожидаясь 2 секунд, в вашем случае асинхронное действие прослушивает данные .listen((data) =>
, поэтому, если вы напечатаете длину за пределами вашего асинхронного действия, вы не увидите деферент, потому что элемент еще не добавлен.
Решение: вы можете создать функцию witch return Future
, а затем дождаться ее завершения, после чего вывести длину.
List<UserSearchItem> userSearchItems = [];
Future<String> submitAll() async {
Firestore.instance
.collection('insta_users')
.snapshots()
.listen((data) =>
data.documents.forEach((doc){
print(data.documents.length);
User user = new User.fromDocument(doc);
UserSearchItem searchItem = new UserSearchItem(user);
userSearchItems.add(searchItem);
print(user.bio);
return 'success';
}));
}
void yourFunction() async{
await submitAll();
print("Loaded");
print(userSearchItems.length);
}
Затем вызовите yourFunction()
.
Комментарии:
1. Спасибо за объяснение! Когда я пробую ваш улучшенный код, он выдает «Выражение await может использоваться только в асинхронной функции». Есть идеи? Спасибо!
2. Оберните все внутри асинхронной функции, я уже обновил пример кода.
3. Спасибо за вашу помощь! Но теперь я получаю другую ошибку: «[Необработанное исключение: NoSuchMethodError: средство получения ‘length’ было вызвано для null». Есть предложения?
4. Да, конечно, поскольку
userSearchItems
он должен быть объявлен внеsubmitAll
функции, чтобы к нему можно было получить доступ изyourFunction
, я обновляю код.5. Хорошо, итак, эта ошибка исчезает 🙂 Но возникло другое: «Необработанное исключение: NoSuchMethodError: метод ‘add’ был вызван при null». Извините, что беспокою вас, но, похоже, вы знаете, о чем говорите!
Ответ №2:
Попробуйте добавить print(userSearchItems.length);
внутри forEach после добавления элемента, и вы увидите реальную длину.
Комментарии:
1. Это работает, но нет ли решения вне цикла?
Ответ №3:
Существует простой способ добавить новые данные в список на Flutter.
for (var i = 0; i < list.length; i ) {
double newValue=newValue 1; //This is just an example,you should put what you'r trying to add here.
list[i]["newValueName"] = newValue; //This is how we add the new value tu the list,
}
Посмотрите, работает ли это, выполнив:
print(list);//You can put a breakpoint her to see it more clearly
Надеюсь, это поможет.