Reputation: 947
I'm using Provider, and Firestore to get some documents that are using the Document Reference Type
in their data model
Is there a good way to get both the data and the nested references in the same "Widget building" pass?
I can retrieve the data, and I can build my classes and widgets from the data, but I'm not able to to update the widgets after I retrieve the referenced documents.
A data model for the object in question would look like this:
{
name: "Check name",
modifiers: [1, 2 ,3],
stats: [stat_reference_one, stat_reference_two]
}
Where stat_reference_one
is a path and the reference type. And it's path is: "/users/.../.../checks/:id"
In my data service I have the following code:
class DataService {
final FirebaseFirestore _db = FirebaseFirestore.instance;
Stream<List<Check>> getChecks() {
var ref = _db.collection(
"/users/.../.../checks/");
return ref.snapshots().map((list) => list.docs.map((doc) {
Map _a = doc.data() as Map<dynamic, dynamic>;
var _alternatives = _a['rollAlternatives']['default'];
List _s = _alternatives['stats'];
List<Stat> SS = [];
_s.forEach((e) => getStat(e.parent.path, e.id).listen((Stat event) {
SS.add(event);
}));
return Check.fromFirestore(doc, statList: SS);
}).toList());
Stream<Stat> getStat(String parentPath, String docId) {
return _db
.collection(parentPath)
.doc(docId)
.get()
.asStream()
.map((doc) => Stat.fromFirestore(doc));
}
There you can see I have two builders aStat.fromFirestore
and a Check.fromFirestore
class Stat {
...
Stat(this.name, this.value);
...
factory Stat.fromFirestore(DocumentSnapshot doc) {
Map data = doc.data() as Map<dynamic, dynamic>;
return Stat(
data['name'],
data['value'],
);
}
}
So, the getChecks
method consumes getStat
and therefore Stat
before trying to create a new Check
object instance. But at the moment it creates the Check
object the stream for Stat
has not finished yet. So my widget is drawn with just the constant values from the modifiers
field. And it's not until I change screen that I see the widget rendered with the result from the stats
field, so it works, but it's not rendered "on time"
Is there a good way to solve for this? I could turn getStat
into a future, but then I wouldn't get the data on stream, which is something I need.
Maybe there's a way to wait for the stream to solve and then return the result of getChecks
I tried to use the onDone
parameter of listen, but that that has a type signature of void.
Thank you in advance
Upvotes: 0
Views: 1345
Reputation: 406
When working with more streams nested to each other, it's wise to use packages like RxDart. Which will ease and smooth your program. https://pub.dev/packages/rxdart
You should definately check out, according to your explanation switchLatest function would do the job for you. https://pub.dev/documentation/rxdart/latest/rx/Rx/switchLatest.html
Let me know if you got questions.
Upvotes: 1