Не удается извлечь данные из вложенной коллекции

# #list #flutter #dart #google-cloud-firestore

Вопрос:

 _getDataRowsForCompletedExerciseSets(workoutId) async { try {  List listOfExercises = await FirebaseFirestore.instance  .collection('users')  .doc(currentUser!.uid)  .collection("workouts")  .doc(workoutId)  .collection("exercises")  .get()  .then((snapShot) =gt; snapShot.docs);   for (int i = 0; i lt; listOfExercises.length; i  ) {  FirebaseFirestore.instance  .collection('users')  .doc(currentUser!.uid)  .collection("workouts")  .doc(workoutId)  .collection("exercises")  .doc(listOfExercises[i].doc.id.toString())  .collection("sets")  .snapshots()  .listen(_createListOfExerciseSets);  }   setState(() {  for (ExerciseSet set in listOfExerciseSets) {  //print(set.weight);  completedExerciseSetRows.add(DataRow(cells: [  DataCell(Text(setCount.toString())),  //const DataCell(VerticalDivider(thickness: 5)),  DataCell(Text(set.weight.toString())),  //const DataCell(VerticalDivider(thickness: 5)),  DataCell(Text(set.reps.toString())),  //const DataCell(VerticalDivider(thickness: 5)),  DataCell((isSetToFailure == true) ? Icon(Icons.check) : Icon(null))  //const DataCell(VerticalDivider(thickness: 5)),  ]));  }  }); } on Exception catch (_, e) {  ScaffoldMessenger.of(context).showSnackBar(  SnackBar(  content: Text(e.toString()),  duration: Duration(milliseconds: 1000),  ),  ); } return Container();  

}

 _createListOfExerciseSets(QuerySnapshot snapshot) {  var docs = snapshot.docs;  for (var doc in docs) {  listOfExerciseSets.add(ExerciseSet.fromFireStore(doc));  }  print('EXERCISE SETS = '   listOfExerciseSets.toString()); }  

У меня есть следующая структура БД:

пользователи—gt;{id}—gt;gt;тренировки—gt;gt;gt;{id}—gt;gt;gt;gt;упражнения—gt;gt;gt;gt; gt; {id}—gt;gt;gt; gt; gt;наборы—gt;gt;gt; gt; gt;gt; gt; {id}—поля

Я пытаюсь получить упражнения для конкретной тренировки(идентификатор) вместе с наборами(включая поля) для каждого упражнения. Список упражнений всегда пуст (0 элементов). Ошибок тоже не видно.

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

1. Пожалуйста, поделитесь также своим ответом Json.

2. Какой ответ json? Я сожалею, что нет ответа json.

3. Я добавил код для _createListOfExerciseSets; хотя listOfExercises отличается от listOfExerciseSets.

4. добавьте немного отладки prints внутрь setState , и вы увидите, что они напечатаны до prints того, как внутри _createListOfExerciseSets — вот почему у вас всегда пустые данные

5. _createListOfExerciseSets-это отдельный метод, который вызывается до вызова setState в _getDataRowsForCompletedExerciseSets. Как я добавляю отпечатки после setState в _createListOfExerciseSets?! В _createListOfExerciseSets нет состояния набора.

Ответ №1:

Вот что у меня есть прямо сейчас:

 Widget build(BuildContext context) {  var exercisesRef = usersRef  .doc(currentUser!.uid)  .collection('workouts')  .doc(workoutId)  .collection('exercises');  return FutureBuilderlt;QuerySnapshotgt;(  future: exercisesRef.get(),  builder: (BuildContext context, AsyncSnapshotlt;QuerySnapshotgt; snapshot) {  switch (snapshot.connectionState) {  case ConnectionState.active:  return const Center(  child: kCPI,  );  case ConnectionState.waiting:  return const Center(  child: kCPI,  );  case ConnectionState.none:  return const Center(  child: kCPI,  );  case ConnectionState.done:  if (snapshot.hasError) {  return Text('Error: ${snapshot.error}');  } else if (!snapshot.hasData) {  //print('WORKOUTID = '   workoutId);  return const Text("Document does not exist");  } else if (snapshot.hasData amp;amp;  snapshot.connectionState == ConnectionState.done) {  final exercises = snapshot.data!.docs;  Listlt;Widgetgt; completedExercisesWidgetsList = [];   final _controller = ScrollController();   // for loop - loop through all the exercises for the current workout  for (var doc in exercises) {  bool isRowsGeneratedForPreviousExercises = false;  dataRowsForCompletedExercises = [];  var setList = [];  Maplt;String, dynamicgt; exercise;  var exerciseName = '';  exercise = doc.data() as Maplt;String, dynamicgt;;  setList = exercise['sets'];  exerciseName = exercise['name'];   //loop through the sets for the exercise   for (var set in setList) {  var setNumber = 0;  var weight = '';  var reps = '';  var isToFailure = false;  setNumber = setList.indexOf(set)   1;  weight = set['weight'].toString();  reps = set['reps'].toString();  isToFailure = set['isToFailure'];  if (isRowsGeneratedForPreviousExercises == false) {  _generateDataTableRowsForCompletedExercises(  setNumber,  weight,  reps,  isToFailure,  );  }  }  isRowsGeneratedForPreviousExercises = true;  completedExercisesWidgetsList  .add(_completedExercisesDataTableWidget(exerciseName));  } //for loop ends   ///Return list of widgets - one widget for each completed exercise for the current workout  return Column(  mainAxisSize: MainAxisSize.max,  children: [  Expanded(   child: ScrollConfiguration(  behavior: ScrollConfiguration.of(context).copyWith(  dragDevices: {  PointerDeviceKind.touch,  PointerDeviceKind.mouse,  },  ),  child: ListView(  shrinkWrap: true,  controller: _controller,  physics: const AlwaysScrollableScrollPhysics(),  scrollDirection: Axis.vertical,  children: completedExercisesWidgetsList,  ),  ),  ),  ],  );  }  }  return const Text("There was a problem loading content.");  },  );  }  

А затем просто генерировать доступные для данных строки из данных:

 void _generateDataTableRowsForCompletedExercises(  setNumber, weight, reps, isToFailure) {  dataRowsForCompletedExercises.add(  DataRow(cells: [  DataCell(Text(setNumber.toString())),  DataCell(Text(weight)),  DataCell(Text(reps)),  DataCell(  (isToFailure == true) ? const Icon(Icons.check) : const Icon(null)),  ]),  );  }  

Ответ №2:

Я полагаю, что ваша проблема в том, где вы используете «тогда»

Попробуйте этот код и посмотрите результаты печати

 var test = await FirebaseFirestore.instance  .collection('users')  .doc(currentUser!.uid)  .collection("workouts")  .doc(workoutId)  .collection("exercises")  .get() print(test);  

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

1. Это дает экземпляр ‘_JsonQuerySnapshot