#flutter #dart #google-cloud-firestore #stream-builder
# #трепетание #дротик #google-облако-firestore #stream-builder
Вопрос:
Я пытаюсь получить целую коллекцию при firestore
использовании StreamBuilder
, но я застрял в отображении результата в соответствии с моей моделью dart
Это поток модели dart.dart:
class Thread {
final String threadTitle;
final String threadContent;
final String threadFlair;
final String threadTimestamp;
final List<String> threadLikedBy;
final List<String> originalPoster;
Thread({
this.threadTitle,
this.threadContent,
this.threadTimestamp,
this.threadFlair,
this.threadLikedBy,
this.originalPoster,
});
factory Thread.fromMap(Map<String, dynamic> map) => Thread(
threadTitle: map["threadTitle"],
threadContent: map["threadContent"],
threadFlair: map["threadFlair"],
threadTimestamp: map["threadTimestamp"],
threadLikedBy: List<String>.from(map["threadLikedBy"].map((x) => x)),
originalPoster: List<String>.from(map["originalPoster"].map((x) => x)),
);
Map<String, dynamic> toMap() => {
"threadTitle": threadTitle,
"threadContent": threadContent,
"threadFlair": threadFlair,
"threadTimestamp": threadTimestamp,
"threadLikedBy": List<dynamic>.from(threadLikedBy.map((x) => x)),
"originalPoster": List<dynamic>.from(originalPoster.map((x) => x)),
};
}
Это виджет, в котором я отображаю результаты в виде списка:
class _ThreadsBodyState extends State<ThreadsBody> {
final threads = _mThreadService.retriveData(path: "posts", builder: (data) => Thread.fromMap(data));
@override
Widget build(BuildContext context) {
return Container(
child: StreamBuilder<Object>(
stream: threads,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemBuilder: (BuildContext context, int index) {
Thread thrd = (snapshot.data as List)[index];
return ThreadCard(thread: thrd,);
},
);
} else {return Text('no data');}
}),
);
}
}
и вот posts_service.dart, где у меня есть функция Stream
//After restructuring my model and adding:
//List<String> threadLikedBy; and List<String> originalPoster;
//this method works no more
Stream<List<T>> retrieveData<T>({
@required String path,
@required T builder(Map<String, dynamic> data),
}) {
final reference = firestoreInstance.collection(path);
final snapshots = reference.snapshots();
return snapshots.map((snapshot) => snapshot.docs.map((snapshot) => builder(snapshot.data())).toList());
}
Похоже, что я путаю отображение в возврате, но я не могу точно понять, как это исправить.
Комментарии:
1. необходимо ли прослушивать данные в реальном времени? похоже, что вы имеете дело с сообщениями в разделе ленты новостей, если это так, дайте мне знать, чтобы я мог предложить решение / обойти.
2. @ThorvaldOlavsen да, это то, что я хочу сделать, но не кажется ли вам, что сообщения должны быть в режиме реального времени?
3. вы можете загружать данные по мере прокрутки пользователем и обновлять, когда пользователь находится в самом верху списка, и он тянет вниз.
4. @ThorvaldOlavsen можете ли вы предоставить свое решение, чтобы я мог попытаться его реализовать?
Ответ №1:
в вашем posts_services.dart добавьте следующую функцию:
Future<QuerySnapshot> fetchThreads() async {
return await firestoreInstance.collection('posts').get();
}
Теперь в вашем виджете, где вы создаете свой ListView
, должно выглядеть так:
class _ThreadsBodyState extends State<ThreadsBody> {
@override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder<QuerySnapshot>(
future: youService.fetchThreads(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.size, //to retrieve the size
itemBuilder: (BuildContext context, int index) {
Thread thrd = Thread.fromMap(snapshot.data.docs[index].data());
return ThreadCard(thread: thrd,);
},
);
} else {return Text('no data');}
}),
);
}
}
Комментарии:
1. это сработало! хотя мне нужно переосмыслить, собираюсь ли я оставить все как есть или вернуться к реальному времени