Flutter 你怎么能在颤振中筑巢?
我有两个流,我需要结合起来构建一个小部件,但不同于我看到的其他问题,我需要嵌套我的流 我有一个从Firestore获取文档集合的流,还有一个依赖于第一个流的数据来获取文档子集合的流。我想将它们合并到一个流中,但它们需要嵌套,因为每个文档都有自己的文档子集合 流1(从FireStore获取习惯集合): 如果您能帮助我将这些流以嵌套格式组合成一个流,以便与flift中的Flutter 你怎么能在颤振中筑巢?,flutter,dart,stream,google-cloud-firestore,Flutter,Dart,Stream,Google Cloud Firestore,我有两个流,我需要结合起来构建一个小部件,但不同于我看到的其他问题,我需要嵌套我的流 我有一个从Firestore获取文档集合的流,还有一个依赖于第一个流的数据来获取文档子集合的流。我想将它们合并到一个流中,但它们需要嵌套,因为每个文档都有自己的文档子集合 流1(从FireStore获取习惯集合): 如果您能帮助我将这些流以嵌套格式组合成一个流,以便与flift中的StreamBuilder一起使用,我将不胜感激 编辑 我不确定我是否朝着正确的方向工作,但我已经尝试实现了spenster的解决方
StreamBuilder
一起使用,我将不胜感激
编辑
我不确定我是否朝着正确的方向工作,但我已经尝试实现了spenster的解决方案,除了上述功能之外,这就是我目前所拥有的
StreamBuilder<List>(
stream: getHabits(),
initialData: [],
builder: (context, snapshot) {
List<UserHabit> habits = [];
List<Widget> test = List.generate(snapshot.data.length, (index){
List<History> history = [];
DocumentSnapshot doc = snapshot.data[index];
return StreamBuilder(
stream: getHistory(doc.documentID, DateTime.utc(2019,7,7), DateTime.now()),
builder: (context, snapshot) {
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting: return new Text('Loading...');
default:
if(!snapshot.data.isEmpty){ //history collection exists
for(int i = 0; i < snapshot.data.length; i++){
//add to history
history.add(History(
day: snapshot.data[i]['day'].toDate(),
dateCompleted: snapshot.data[i]['dateCompleted'].toDate(),
morning: snapshot.data[i]['morning'],
afternoon: snapshot.data[i]['afternoon'],
evening: snapshot.data[i]['evening'],
anytime: snapshot.data[i]['anytime'],
));
}
}
habits.add(UserHabit(
name: doc['habit'],
color: doc['color'],
icon: doc['icon'],
repeat: doc['repeat'],
daily: doc['daily'],
weekly: doc['weekly'],
monthly: doc['monthly'],
time: doc['time'],
history: history,
));
print(habits); //returns each iteration of assembling the list
return Text("i dont want to return anything");
}
},
);
}
);
print(habits); //returns empty list before anything is added
return Column(
children: test,
);
},
),
StreamBuilder(
流:getHabits(),
初始数据:[],
生成器:(上下文,快照){
列出习惯=[];
列表测试=列表.generate(snapshot.data.length,(索引){
列表历史=[];
DocumentSnapshot doc=snapshot.data[索引];
返回流生成器(
流:getHistory(doc.documentID,DateTime.utc(2019,7,7),DateTime.now()),
生成器:(上下文,快照){
if(snapshot.hasError)
返回新文本('Error:${snapshot.Error}');
交换机(快照.连接状态){
case ConnectionState.waiting:返回新文本('Loading…');
违约:
如果(!snapshot.data.isEmpty){//历史记录集合存在
对于(int i=0;i
UserHabits和History类可以共享,但它们只是分配类型并允许轻松访问的基本类 我简单地使用嵌套的
StreamBuilders
做了类似的事情。根据您希望小部件的组织方式,您可以在外部StreamBuilder
中创建流。根据您的澄清意见,这是一种可能性:
@override
Widget build(BuildContext context) {
var habits = Firestore.instance
.collection("users")
.document('VtL1sxOoCOdJaOTT87IbMRwBe282')
.collection("habits")
.snapshots();
return StreamBuilder<QuerySnapshot>(
stream: habits,
builder: (context, snapshot) {
if (!snapshot.hasData)
return Text("Loading habits...");
return ListView(children: snapshot.data.documents.map((document) {
var query = Firestore.instance
.collection("users")
.document('VtL1sxOoCOdJaOTT87IbMRwBe282')
.collection("habits")
.document(document.documentID)
.collection("history")
.where('day', isGreaterThanOrEqualTo: start)
.where('day', isLessThanOrEqualTo: end)
.snapshots();
return StreamBuilder<QuerySnapshot>(
stream: query,
builder: (context, snapshot) {
if (!snapshot.hasData) return Text("Loading...");
// right here is where you need to put the widget that you
// want to create for the history entries in snapshot.data...
return Container();
},
);
}).toList());
},
);
}
@覆盖
小部件构建(构建上下文){
var=Firestore.instance
.收集(“用户”)
.document('VtL1sxOoCOdJaOTT87IbMRwBe282')
.收集(“习惯”)
.快照();
返回流生成器(
溪流:习惯,
生成器:(上下文,快照){
如果(!snapshot.hasData)
返回文本(“加载习惯…”);
返回ListView(子项:snapshot.data.documents.map((文档){
var query=Firestore.instance
.收集(“用户”)
.document('VtL1sxOoCOdJaOTT87IbMRwBe282')
.收集(“习惯”)
.document(document.documentID)
.收藏(“历史”)
.其中('day'大于或等于:开始)
.where('day',isLessThanOrEqualTo:end)
.快照();
返回流生成器(
流:查询,
生成器:(上下文,快照){
如果(!snapshot.hasData)返回文本(“正在加载…”);
//在这里,您需要放置您需要的小部件
//要为快照中的历史记录条目创建。数据。。。
返回容器();
},
);
}).toList());
},
);
}
尝试使用类似于可观察的.zip2(stream1,stream2,zipper)
或可观察的.combineLatest2(streamA,streamB,combiner)的东西来合并流。
有关更多信息,请查看此谢谢!我会试一试,如果成功的话,我会把你的答案标记为正确!我感谢你花了这么多时间来回答!出于好奇,我有没有办法在getHistory
StreamBuilder
中不返回任何内容?我需要使用历史记录的列表
数据来查看事情是否完成,但我在getHabits()
中只为每个项目构建了一个小部件。我还得到了以下错误元素类型“Set”无法分配给列表类型“widget”。
如果您只想从历史记录中获取一个文档,然后您可以使用Firestore来选择它(比如在查询中使用.limit(1)),然后只构建一个小部件。这也顺便消除了你看到的另一个错误。我会看看是否可以更新答案……我想我已经设法让这个方法发挥作用了,但我觉得应该有一种方法可以嵌套流,而不需要嵌套StreamBuilder。或者firebase应该可以更容易地访问子文档哈哈。非常感谢您的时间,我会把这个标记正确的!我已经花了大约一周的时间研究这一难题。我喜欢它的发展方向,但第二个流取决于第一个流中某个项目的documentID
。第二个流对于来自
StreamBuilder<List>(
stream: getHabits(),
initialData: [],
builder: (context, snapshot) {
List<UserHabit> habits = [];
List<Widget> test = List.generate(snapshot.data.length, (index){
List<History> history = [];
DocumentSnapshot doc = snapshot.data[index];
return StreamBuilder(
stream: getHistory(doc.documentID, DateTime.utc(2019,7,7), DateTime.now()),
builder: (context, snapshot) {
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting: return new Text('Loading...');
default:
if(!snapshot.data.isEmpty){ //history collection exists
for(int i = 0; i < snapshot.data.length; i++){
//add to history
history.add(History(
day: snapshot.data[i]['day'].toDate(),
dateCompleted: snapshot.data[i]['dateCompleted'].toDate(),
morning: snapshot.data[i]['morning'],
afternoon: snapshot.data[i]['afternoon'],
evening: snapshot.data[i]['evening'],
anytime: snapshot.data[i]['anytime'],
));
}
}
habits.add(UserHabit(
name: doc['habit'],
color: doc['color'],
icon: doc['icon'],
repeat: doc['repeat'],
daily: doc['daily'],
weekly: doc['weekly'],
monthly: doc['monthly'],
time: doc['time'],
history: history,
));
print(habits); //returns each iteration of assembling the list
return Text("i dont want to return anything");
}
},
);
}
);
print(habits); //returns empty list before anything is added
return Column(
children: test,
);
},
),
@override
Widget build(BuildContext context) {
var habits = Firestore.instance
.collection("users")
.document('VtL1sxOoCOdJaOTT87IbMRwBe282')
.collection("habits")
.snapshots();
return StreamBuilder<QuerySnapshot>(
stream: habits,
builder: (context, snapshot) {
if (!snapshot.hasData)
return Text("Loading habits...");
return ListView(children: snapshot.data.documents.map((document) {
var query = Firestore.instance
.collection("users")
.document('VtL1sxOoCOdJaOTT87IbMRwBe282')
.collection("habits")
.document(document.documentID)
.collection("history")
.where('day', isGreaterThanOrEqualTo: start)
.where('day', isLessThanOrEqualTo: end)
.snapshots();
return StreamBuilder<QuerySnapshot>(
stream: query,
builder: (context, snapshot) {
if (!snapshot.hasData) return Text("Loading...");
// right here is where you need to put the widget that you
// want to create for the history entries in snapshot.data...
return Container();
},
);
}).toList());
},
);
}