Let's Code Flutter: Widget Notifications
Working with Flutter (and therefore, Dart) has been an interesting learning experience. I'm still #TeamKotlin, but my job has a Flutter app so I needed to get acquainted with how things work. My first real learning curve came in trying to understand the BLoC pattern, coming from an MVP Android app.
I don't think I have a full grasp on that yet, so this is not that blog post.
The way I understand BLoC pattern currently, they are not actually supposed to really hold references to models. The BLoC is purely for logic. (Whoops. Vast departure from MVP.) Additionally, the original developers passed the BLoC down through multiple Widget levels — either that, or multiple Streams or Sinks. Something about this just didn't feel right. (Please correct me if I'm wrong! The BLoC pattern conflicts with everything I know. 😭)
In the process of understanding the BLoC pattern — and the sea of Streams/Sinks that I have — I learned how to send notifications up the Widget tree, and that's with... Notifications! I don't know the current Best Practice ™ for using them, sadly. But at the moment, they fit my needs.
Listening for Notifications
Quick recap: Flutter UI is just a huge tree of Widgets. You've clicked 3 pages down on a button in the center? It's a child of almost 100 Widgets at this point. Notifications serve the purpose of "bubbling up" messages from children to their ancestors.
A good example would be a built in Notification: ScrollNotification. If you use a Scrollable Widget, and need to keep track of scrolling events, you would listen for a ScrollNotification. And as with more things in Flutter, you listen to a Notification using another Widget: NotificationListener.
var widget = Scaffold(
body: NotificationListener<ScrollNotification>(
onNotification: (notification) {
//do things with the notification here
return true;
},
child: Container(
child: ...,
),
),
);
Somewhere in that Container will be a Scrollable widget, and we want to listen for a ScrollNotification. When the notification is dispatched, this Widget will catch it and act upon it. If we want to make it available to other ancestors, simply return false;
, otherwise return true
to make it stop bubbling up the tree.
That's it!
Make your own Notification
Making your own custom Notification is easy.
class SomeExampleNotification extends Notification {
final String name;
SomeExampleNotification(this.name);
}
To make a notification you would simply extend Notification
, then make the class as you see fit. You would then listen for this Notification like you would a ScrollNotification.
My Current Dilemma
At the moment, I'm facing one tiiiiny little issue, which may not be an actual issue. I've already encountered at least one instance where I want to listen to multiple Notifications, and would prefer to do them at about the same hierarchy as each other in the tree. However, NotificationListener only allows listening to one type of Notification, meaning I end up with nested NotificationListeners.
NotificationListener<OneNotification>(
onNotification: (notification) {
// do things
return true;
},
child: NotificationListener<TwoNotification>(
onNotification: (notification) {
// do more things
return true;
},
child: Container(child: ...)
This seems weird to me, but outside of wrapping the two notifications in another (or just making one with different types), I can't see a better way of doing this.
If you have any ideas of how to better address this, let me know in the comments! Help me out! lol