Я пытаюсь создать список, чтобы отображать некоторые события с их соответствующими пользователями, но список создается до завершения метода, а затем получается пустой список ...
Я пробовал это, но проблема все еще сохраняется:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:project/Methods.dart';
import 'package:project/Views/CadastroUsuario.dart';
import 'package:project/classes/eventos.dart';
class ListagemEventos extends StatefulWidget {
@override
ListagemEventosState createState() => new ListagemEventosState();
}
class ListagemEventosState extends State<ListagemEventos> {
@override
void initState() {
super.initState();
}
Future<List<Event>> getEvents() async {
CollectionReference eventsDoc = Firestore.instance.collection("events");
return await eventsDoc.getDocuments().then((snapshot) {
List<Event> events = new List<Event>();
snapshot.documents.forEach((doc) async {
Event event = new Event();
String id;
event.description = doc["description"];
event.city = doc["city"];
event.state = doc["state"];
event.location = doc["location"];
event.date = doc["date"];
event.placesAvailable = doc["placesAvailable"];
event.totalPlaces = doc["placesTotal"];
id = doc["userId"];
event.owner = new UserOwner();
CollectionReference eventsDoc = Firestore.instance.collection("users");
event.owner = await eventsDoc.document(id).get().then((doc) {
UserOwner userOwner = new UserOwner();
userOwner.userid = id;
userOwner.name = doc["name"];
userOwner.phone = doc["phone"];
userOwner.email = doc["email"];
userOwner.city = doc["city"];
userOwner.state = doc["state"];
userOwner.photo = doc["photo"];
event.owner = userOwner;
return userOwner;
});
events.add(event);
});
return events;
});
}
Widget createListView(BuildContext context, AsyncSnapshot snapshot) {
List<Event> events = snapshot.data;
return new ListView.builder(
itemCount: events.length,
itemBuilder: (BuildContext context, int index){
return item(events[index]);
},
);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Eventos'),
),
body: new FutureBuilder(
future: getEvents(),
builder: (BuildContext context, AsyncSnapshot snapshot){
switch (snapshot.connectionState) {
case ConnectionState.waiting: return new Text("Loading...");
default:
if (snapshot.hasError)
return new Text("Erro: ${snapshot.error}");
else
return createListView(context, snapshot);
}
},
),
floatingActionButton: new FloatingActionButton(
tooltip: 'Novo',
child: new Icon(Icons.add),
onPressed: () async {
Navigation navigation = new Navigation();
navigation.navigaTo(context, CadastroUsuario());
},
),
);
}
Widget item(Event event) {
return new Card(
elevation: 4.0,
child: new Column(
children: <Widget>[
new Row(
children: <Widget>[
new Column(
children: <Widget>[
new Text(event.owner.name.toString(),
style: TextStyle(fontSize: 20.0),
overflow: TextOverflow.ellipsis,),
],
),
new Column(
children: <Widget>[
],
)
],
),
new Container(
color: Colors.blue,
height: 150.0,
),
new Row(
children: <Widget>[
new Row(
children: <Widget>[
new Text(event.description.toString(),
style: TextStyle(fontSize: 20.0),
overflow: TextOverflow.ellipsis,),
],
),
new Row(
children: <Widget>[
new Text(event.location.toString(),
style: TextStyle(color: Colors.grey[350]),
overflow: TextOverflow.ellipsis,),
],
),
new Row(
children: <Widget>[
new Text(event.city.toString() +' - '+ event.state.toString(),
style: TextStyle(color: Colors.grey[350]),
overflow: TextOverflow.ellipsis,),
],
)
]
)
],
)
);
}
}
Как я могу решить эту проблему? Есть ли другой способ сделать это?
PS: Я был бы признателен, если бы вы тоже привели мне пример
Он работает нормально, проблема в том, что getevents завершает работу после завершения Listview.builder.

Поскольку я не могу запустить ваш код, потому что он имеет другие зависимости, я постараюсь помочь вам как можно лучше, не тестируя его.
Одна вещь, которую следует помнить о флаттере (что значительно упростило мне понимание), заключается в том, что представление никогда не обновляется, пока вы не вызовете этот метод.
this.setState(() {});
Поэтому, когда вы на 100% уверены, что данные загружены, вызовите эту функцию. Это перестроит ваше представление и снова вызовет функцию сборки, которая должна обновить ваше представление. Я надеюсь, это поможет вам.
Зная это, вы могли бы значительно упростить свой код. Вы можете просто создать список с переменной как Children. Заполните эту переменную в своей асинхронной функции и снова вызовите setState. Это заполнит список.
Он использует FutureBuilder, который устраняет необходимость в setState. Это не связано
Спасибо, но если я вызову setState после загрузки всех данных, мое приложение зайдет в бесконечный цикл.
Опять чувак ... Спасибо, ты заставил меня думать иначе, и я нашел способ решить свою проблему! Отмечу ваш ответ, потому что вы помогли мне увидеть другой путь!
Наконец-то я нашел способ ...
Я инициализирую слушатель в initState, и когда в моем хранилище меняются изменения, я использую setState для восстановления обычного представления списка.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:project/Methods.dart';
import 'package:project/Views/CadastroUsuario.dart';
import 'package:project/classes/eventos.dart';
class ListagemEventos extends StatefulWidget {
@override
ListagemEventosState createState() => new ListagemEventosState();
}
class ListagemEventosState extends State<ListagemEventos> {
List<Event> _events;
@override
void initState() {
super.initState();
_events = new List<Event>();
Firestore.instance.collection("events").snapshots().listen((snapshot){
getEvents(snapshot);
});
}
void getEvents(QuerySnapshot eventsDoc) {
List<Event> events = new List<Event>();
eventsDoc.documents.forEach((doc) async {
Event event = new Event();
String id;
event.description = doc["description"];
event.city = doc["city"];
event.state = doc["state"];
event.location = doc["location"];
event.date = doc["date"];
event.placesAvailable = doc["placesAvailable"];
event.totalPlaces = doc["placesTotal"];
id = doc["userId"];
event.owner = new UserOwner();
CollectionReference eventsDoc = Firestore.instance.collection("users");
event.owner = await eventsDoc.document(id).get().then((doc) {
UserOwner userOwner = new UserOwner();
userOwner.userid = id;
userOwner.name = doc["name"];
userOwner.phone = doc["phone"];
userOwner.email = doc["email"];
userOwner.city = doc["city"];
userOwner.state = doc["state"];
userOwner.photo = doc["photo"];
event.owner = userOwner;
return userOwner;
});
events.add(event);
setState(() {
_events = events;
});
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Eventos'),
),
body:
_events.length == 0
?
new Center(child: new CircularProgressIndicator())
:
new ListView.builder(
itemCount: _events.length,
itemBuilder: (BuildContext context, int index){
return item(_events[index]);
}
)
,floatingActionButton: new FloatingActionButton(
tooltip: 'Novo',
child: new Icon(Icons.add),
onPressed: () async {
Navigation navigation = new Navigation();
navigation.navigaTo(context, CadastroUsuario());
},
),
);
}
Widget item(Event event) {
return new Card(
elevation: 4.0,
child: new Column(
children: <Widget>[
new Row(
children: <Widget>[
new Column(
children: <Widget>[
new Text(event.owner.name.toString(),
style: TextStyle(fontSize: 20.0),
overflow: TextOverflow.ellipsis,),
],
),
new Column(
children: <Widget>[
],
)
],
),
new Container(
color: Colors.blue,
height: 150.0,
),
new Row(
children: <Widget>[
new Row(
children: <Widget>[
new Text(event.description.toString(),
style: TextStyle(fontSize: 20.0),
overflow: TextOverflow.ellipsis,),
],
),
new Row(
children: <Widget>[
new Text(event.location.toString(),
style: TextStyle(color: Colors.grey[350]),
overflow: TextOverflow.ellipsis,),
],
),
new Row(
children: <Widget>[
new Text(event.city.toString() +' - '+ event.state.toString(),
style: TextStyle(color: Colors.grey[350]),
overflow: TextOverflow.ellipsis,),
],
)
]
)
],
)
);
}
}
Можете ли вы проверить, действительно ли
getEventsработает и возвращает непустой набор данных? Может быть, напишите тест, чтобы сначала проверить, если это возможно.