Список.карта не выполняется, несмотря на то, что в списке есть элементы внутри (flutter)

#flutter #dart

#флаттер #dart

Вопрос:

Я извлекаю a querysnapshot из Firestore, который возвращает список querydocumentsnapshot с snapshot.docs, но когда я пытаюсь сопоставить его, ничего не происходит. Если я использую for...in цикл, он работает отлично.

      QuerySnapshot snap =
        await FirebaseFirestore.instance.collection('Products').doc(FirebaseAuth.instance.currentUser.uid).collection('ItemDetails').get();
    print(snap.docs);//returns [Instance of 'QueryDocumentSnapshot', Instance of 'QueryDocumentSnapshot', Instance of 'QueryDocumentSnapshot']

    for (var item in snap.docs.toList()) {//this executes perfectly
      print(item.data());
    }
    snap.docs.toList().map((e) => print(e.data().toString()));//this won't execute
    snap.docs.map((e) => print(e.data().toString()));//this won't execute
  

Почему .map() не работает, когда for цикл выполняется?

Комментарии:

1. Если вы не собираетесь использовать результат List.map , тогда List.forEach или for цикл будет более подходящим. Смысл использования List.map заключается в создании нового List .

Ответ №1:

Это связано с тем, как map работает метод. Согласно документации —

метод map<T>

 Iterable<T> map <T>(

    T f(
        E e
    )

) 
  

Возвращает новую отложенную итерацию с элементами, которые создаются путем вызова
f для каждого элемента этой итерации в порядке итерации.

Этот метод возвращает представление отображенных элементов. До тех пор, пока возвращаемый итерируемый объект не будет повторен, предоставленная функция f не будет вызвана. Преобразованные элементы не будут кэшироваться. Многократное повторение возвращаемой итерации приведет к вызову предоставленной функции f несколько раз для одного и того же элемента.

Методам возвращаемой итерации разрешено не вызывать f для любого элемента, где результат не нужен. Например, ElementAt может вызвать f только один раз.

В вашем примере, поскольку вы не выполняете итерацию по результату Iterable , он не вызовет функцию. Так что, если вы измените свой код на это

 snap.docs.map((e) => print(e.data().toString())).toList();
  

затем он будет выполнен, потому что теперь ему нужно выполнить итерацию по результату Iterable , чтобы преобразовать его в a List .

Ответ №2:

List.map создает итерацию, но фактически не выполняет итерацию по ней. Вы можете увидеть это в этом примере:

 List<String> s = ["a", "b", "c"];

var i = s.map((e){
  print(e);
});

i.toList(); //prints a, b, c
  
  

Вы можете принудительно вызвать его, вызвав .ToList() вот так:

 List<String> s = ["a", "b", "c"];

var i = s.map((e){
  print(e);
}).toList(); //prints a,b,c

print(i.length); //3
  
  

Комментарии:

1. Спасибо, ваши примеры помогли мне лучше понять проблему