Reputation: 4575
In a screen, a Firebase list has logic applied to
I want to count the blue widgets.
What is the best way to do this?
return new StreamBuilder<int>(
stream: subscribeMyThings(thing.id),
builder: (context, thingsSnapshot) {
return new FirebaseAnimatedList(
query: getThings(thing.id),
itemBuilder: (context, snapshot, animation, index) {
return new ReactiveWidget<int>(
reactiveRef: getThingBlueness(snapshot.key),
widgetBuilder: (checkBlueness) {
// code to check blueness here
// if Thing is blue, place empty container
if (thingIsBlue) {
return new Container();
// *** how do I count these??? ***
}
// or, if Thing is NOT blue
return new Thing(thing.id);
);
},
);
);
}
Upvotes: 3
Views: 1900
Reputation: 8360
I think you are not hitting the problem from the proper point of view, plus the title is misleading.
You might not intend to count the widget shown on the screen, but rather count a subset of Firebase database entries that fit some conditions. This makes a big difference in Flutter, since counting widgets involves the the render tree, the layouts and graphics in general, while it looks you want to address a data problem.
If I am right then you might consider having an index in your db keeping track of the number of blue items and listen to it in another streambuilder.
Long story short, you might want to keep a map< id, blueness >, update each element at build time, and iterate over the map whenever required to count.
// somewhere in your outer scope
Map<int, bool> _bluenessMap = new Map<int, bool>();
return new StreamBuilder<int>(
stream: subscribeMyThings(thing.id),
builder: (context, thingsSnapshot) {
return new FirebaseAnimatedList(
query: getThings(thing.id),
itemBuilder: (context, snapshot, animation, index) {
return new ReactiveWidget<int>(
reactiveRef: getThingBlueness(snapshot.key),
widgetBuilder: (checkBlueness) {
// code to check blueness here
// ----------------------------
// before return let us update the map
_bluenessMap[thing.id] = thingIsBlue
// ----------------------------
// if Thing is blue, place empty container
if (thingIsBlue) {
return new Container();
}
// or, if Thing is NOT blue
return new Thing(thing.id);
);
},
);
);
}
// call me when you want to count
int fancyBlueCounter(){
int result = 0;
for(bool isBlue in _bluenessMap.values){
if(isBlue) result += 1;
}
return result;
}
Edit
Since the author of the question confirmed it is a "data problem", I feel like suggesting another (maybe better) way to address it.
Aggregates or Indexes are (in my opinion) the proper way to solve your problem. Anytime someone touches a Thing depending on its blueness it refreshes a purposefully created aggregate in the DB (actually also a simple data entry count). You can do this either following any function editing Things with a transaction updating the blue count, or with cloud functions (see doc here) listening for changes events (creation, deletion, and edit) and updating the count as well.
Upvotes: 3