Mixins might sound scary, but in essence, it’s just a way of reusing code. If you have any animation in your app, you already use at least one of them (SingleTickerProviderStateMixin, TickerProviderStateMixin). Mixins are just classes without constructors that store shareable code. You have already known it from documentation, so my goal here is to show how to embrace mixins to help you keep Flutter app’s code dry (“Don’t repeat yourself”).
“Guns for show, knives for a pro”
Imagine you are working on an app with several ListView pages. All of them share the same logic:
👇 if user scrolls to the bottom of a list then the app should fetch more items (infinite scroll);
👆user can “pull to refresh”;
✋ prevent triggering fetch event multiple times if data is already fetching;
Very common stuff, right?
For example, we have three pages with ListViews: CollectionsScene(), WinesScene() and TagsScene().
Assuming all of them have ScrollController scrollController to manage ListView’s scrolling, we can implement the “infinite scroll” feature like this:
And simplified “pull to refresh” logic looks like:
In some cases, we would want to prevent triggering fetch event. For example, if we reach the last item of a list or fetching data is already in progress. Also, it takes some time to return scroll to default position after pulling the list down to refresh, and we don’t want to trigger refresh events multiple times during that time. Keeping all of these things in mind the trigger function may look like this:
“A minute ago this was the safest job in the world. Now it’s turning into a bad day in Bosnia”
Let’s bring it all together in WinesScene widget:
We have two more widgets left. And now I can hear you whispering: “But wait, we can easily reuse a hell of amount of code in other two widgets”. And I’m glad you bring it up! Let’s create a mixin!
Soap: Armed with what?
Eddy: Err, bad breath, colorful language, feather duster… what do you think they’re gonna be armed with?
Mixin is just a class without constructor:
First of all, we would like to use our mixin with StatefulWidgets only and we want to be sure the fetch method is implemented. That is why we use <…> notation to specify the type of objects and implementing an abstract class with a fetch method:
We can also move the initiation code to mixin along with the rest of the code:
We have moved all our code we want to reuse from the widget to mixin.
And now all we have to do is just tell our WinesScene widget about newly created mixin…
“What I do know is there’s no more Harry. Which means there’s no more debt.”
Boom! As you can see now our widget is much leaner and describes only unique features like scene UI and tells us what we need to fetch (wines). The other two pages CollectionsScene() and TagsScene() will do the same (build a unique UI and fetch collections and tags) while ListSceneMixin keeps the common code.