Flutter добавить элемент в список

#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 
  

Надеюсь, это поможет.