The Fluttery Framework
A Framework that works with Flutter and works like Flutter
Mike Rydstrom is known to post on his Twitter account a list of the Top 30 State Management library packages used by Flutter developers. Below, I believe, is the latest dated August 14, 2022. Tap on it to get a closer look.
Google didn’t release Flutter ‘hard coded’ to one particular architecture. They left it to the IT industry to come up with different ways to work with Flutter. Hence the list above. After all, programming languages are called upon to work in almost every Use Case on Earth! Computer software can be found running in everything from a toaster to a nuclear submarine. By that very fact, it has to be intrinsically adaptive so as to meet very diverse and very complicated problem domains. Google knew you simply can’t supply a ‘one-size-fits-all’ approach when developing software. And so, I suspect that list will only grow longer.
Of course, your users and particularly your boss will insist you only use the ‘best one’ listed above — which, as I’ve just hinted, is an impractical demand. However, time is money and in many cases, I suspect you’ll choose one simply because it follows a design pattern or style you’re familiar with. Still, other developers will look at that list, visit forums, ask around, and then simply pick what seems to be the most popular. Easy peasy.
However, it’s not so easy. I’ve looked at that list — for most, you have to learn how to use your chosen approach. Today, I’ll introduce you to yet another library package. One I feel stands out from the rest. ‘Keep it Flutter’ has been my motto when building this framework. Most of those other library packages don’t work like Flutter itself. They sit on top of Flutter and have their own way of doing things. There‘s a learning curve not only to learn how Flutter works but how your chosen library package works as well.
Below is a ‘paywalled’ article about the Provider package. The article is written by Suragch — one of my favorite writers. I’ve always liked the title, Making sense of all those Flutter Providers. The Provider state management package was written by Remi Rousselet, and to me, looks a lot like the Provider Model introduced by Microsoft in 2002 — I suspect many of today’s Provider users were ASP.Net developers.
Remi did some great work, but I chose not to use Provider. After all, Flutter has its own means of State Management. I wrote a framework to more effectively and more efficiently work with Flutter — like Flutter.
If you’re new to Flutter and want to learn Flutter, learn how to use this library package. Unlike those others, it’s a framework that works with Flutter, works like Flutter, and looks like Flutter. If you have a few years of experience in Flutter, you’ll recognize how this framework works. In this series of articles, you’ll be introduced to the Fluttery Framework through the demonstration of a number of example apps.
I Like Screenshots. Tap Caption For Gists.
As always, I prefer using screenshots in my articles over gists to show concepts rather than just show code. I find them easier to work with frankly. However, you can click or tap on their captions to see the code in a gist or in Github. Tap or click on the screenshots themselves to zoom in on them for a closer look. If reading on your phone, use two fingers to expand and collapse the image. Ironically, you may find it best to read this article about mobile development on your computer rather than on your phone.
No Moving Pictures, No Social Media
There will be gif files in this article demonstrating aspects of the topic at hand. However, it’s said viewing such gif files is not possible when reading this article on platforms like Instagram or Facebook. They may come out as static pictures or simply blank placeholders. Please, be aware of this and maybe read this article on medium.com or on their own app.
Let’s begin.
Works with Flutter, Works Like Flutter
This framework implements a SOC (State Object Controller) to accompany every State object used in your Flutter app. It does this by introducing the class, StateX, which ‘extends’ Flutter’s State class to now include a controller. It is this controller object that performs the event handling and business rules specific to your app — much like the many Controller objects already found in Flutter. Again, I’m ‘keeping it Flutter.’
Indeed, there are a number of widgets in Flutter with a named parameter called, controller. The widgets, TextField and SingleChildScrollView, are two quick examples. They take in a controller object that provides an initial value or an initial position respectively as well as handle the common events and circumstances involved in their typical operation. It was back in 2018 when I first began working in Flutter that I quickly found it very productive and advantageous to introduce such a controller to Flutter’s own State class.
Below are two screenshots of those two widgets I mentioned above — each with its own controller parameter highlighted with a little red arrow.
By Example
Now, what better way to illustrate the implementation of the StateX class and the Fluttery Framework than demonstrating it in an example app? The Stocks example app implements the Fluttery Framework. This little app supplies the option, ‘dev tools’, in its Drawer widget demonstrating the many development tools available to you when working in Flutter. In truth, it’s the Fluttery Framework that makes these tools readily available to you, and I’ll show you how in later articles but for now, let’s look at this StateX class and its controller.
The State Extended
In the first screenshot below, you’re introduced to the StateX class for the first time. The little red arrows highlight this class and how its accompanying controller, DevTools, is instantiated. It’s the StatefulWidget, StockSettings, that presents the list of switches you see turning on and off an assortment of development tools. (Note, these tools can only be accessed while developing in your IDE or when you compile your Flutter app in debug mode.)
The second screenshot above is a portion of that State object’s build() function displaying two of those switches. Note the distinct separation of work: the State object’s build() function is concerned with ‘how’ things are displayed in the interface (i.e. with its Switch widgets) while its controller instantiated to the property variable, con, is more concerned with what’s actually being displayed as well as any event handling —this separation of responsibility is a core concept in clean architecture.
The Controller Pattern
By the way, that’s the consistent pattern you’ll see in the Fluttery Framework example apps:
A controller is passed to the StateX object’s parent class constructor, it’s then assigned to a property variable (usually named ‘con’) either in the StateX class’ constructor or in its initState() function. That ‘con’ variable is then referenced here and there in the build() function and in any other function defined in that class and will primarily be invovled in the app’s overall business logic and event handling.
The first screenshot is again displayed below for your review. Further below, you’ll find those development tools displayed individually. Most are concerned with the fine-tuning of your app’s interface. In time, you’ll find them very useful in certain circumstances.
Set The State
Now, all that flash and color you see displayed above just doesn’t magically appear when using Flutter. As a quick aside, we know HTML is a declarative programming language. When there’s a change made to a webpage, in most cases, that whole webpage is rendered all over again to then display that change. Well, Flutter apps create their interfaces in a pseudo-declarative fashion as well. This declarative characteristic of ‘rebuilding the interface all over again from scratch’ comes with every new call to a State object’s build() function —the returning widget is often the result of a bunch of other widgets being built all over again. However, that call has to be made in the first place using the State object’s setState() function.
You can readily see above those Switch widgets being turned on and off. However, that’s only because the StatefulWidget, StockSettings, is being rebuilt all over again. More accurately, its State object, _StockSettingsState, is having its build() function called again and that function’s content is being rebuilt all over again. In that screen full of Switch widgets, that State object’s setState() function is being called somewhere. But where?
Below, you see the ‘Performance overlay’ switch being turned on and off repeatedly. The first screenshot below highlights the Switch widget’s onChange() function. With every tap of the widget, that onChange() function is called, and as you can see, its controller is in charge of handling that event. So where is the setState() function call? The Switch can be seen turning on and off with every tap. There has to be a setState() function being called?! Well yes, yes there is. Look at the second screenshot below.
The second screenshot above is of the setter, showPreformanceOverlay, found in the controller, DevTools. There you see the new Switch value being received and recorded (true equals ‘on’ and false equals ‘off’). However, you also see a setState() function call! When a controller is taken in by the StateX object, it can do whatever a State object can do…and more. The controller, DevTools, extends from another class found in the Fluttery Framework called, StateXController.
class DevTools extends StateXController {
The DevTools class was instantiated and passed to the State object’s parent constructor, remember? It now has access to that State object and all its capabilities. Below, that one line is commented out and the program run again. It reveals that this access is indeed true. The switch continues to be turned on and off, however, nothing appears to be happening. That’s because the screen simply hasn’t been refreshed — the widgets involved have not been rebuilt. In other words, the State object’s setState() function hasn’t been called again — through its controller, DevTools. We’re failing in our State Management duties. However, the performance overlay is indeed on when returning to the app’s home screen.
Keeping It Flutter
Note, how I ‘kept it Flutter,’ with a separate subclass derived from the class, StateXController, yet using the very same function name, setState()? It simply is calling the original setState() function in a State object! All the packages on that list are doing the same thing. Note, some are even calling the markNeedsBuild() function deeper in the Flutter framework itself to achieve the same thing. Something I chose not to do.
That function resides in the Element class, and personally, that’s too deep in Flutter’s own framework. It’s in the realm where the Google engineers only play. The markNeedsBuild() function is not part of the public API like setState() — it’s the setState() function that calls the markNeedsBuild() function. Frankly, there‘s the chance that the markNeedsBuild() function will go away a few years from now when they release Flutter 7.0 for example. Like any shop, Google will want its software to easily evolve and has only designated the setState() function to be used when notifying Flutter of a change in state.
Again, those other packages up on that list are using completely different paradigms to perform their State Management (i.e. to call setState() in some State object) using completely different function names.
Keep it Flutter.
Back to Fluttery. Note, these SOC’s (State Object Controllers) can be assigned, to any number of StateX objects throughout the lifetime of a Flutter app. For example, with each new StateX object (i.e. with each successive screen), a controller can be shared among them working with a particular State object before retreating back to the previous State object when that screen closes. Sure, Flutter’s State objects are to retain the state of the app, but now you have a StateXController object providing steadfast logic, and indeed, managing that state. The graphic below illustrates this “Last In First Out” (LIFO) relationship that occurs when a SOC is shared among progressive and then receding Flutter screens.
Further, your StateX object is allowed to take in as many controllers as you like. Each controller can be responsible for a particular functionality — ready to react to the many events that originate from that StateX object. See the graphic below. This ability encourages modular programming and allows for parallel development. Very nice.
Developing Your Tools
By the way, I should explain how those development tools are then displayed to you after you’ve selected one or more. In Flutter, rebuilding that screen full of Switch widgets isn’t enough. Yes, that’ll show the switch has changed, but nothing else would happen. You would have to also render the whole app over again! More accurately, call the setState() function of the app’s first State object. With me so far? I’m keeping it Flutter.
There’s a StateX object that’s the first State object or root State object for your app when using the Fluttery Framework. And in this case, we have to call its setState() function to now display that Performance Overlay for example. Let’s show you how that works. However, I bet you’ve already got a good guess…if you know Flutter.
The screenshot above shows part of the Drawer widget displaying the option, Debug Tools. Again, it’s a controller (this one is called StockHomeController) that handles things if the option is tapped on. Unbeknownst to you, that controller calls the controller, DevTools, to bring up that screen of switches —thus deligating the work among different controllers and keeping it modular. See the first screenshot below.
Note, that ‘Debug Tools’ option will not appear if the app is released into production (see above) courtesy of the Flutter Framework’s static getter, App.inDebugger (also App.inDebugMode). This Fluttery Framework library package doesn’t just provide a means for State Management. It’s a framework! Frameworks are supposed to make development a little easier. Anyway, the majority of Flutter’s development tools aren’t available in Production anyway — why confuse the user with such an option?
Remember to tap on the screenshots for a closer look. If you’re on your phone, you can then use two fingers to zoom in even further.
After the ‘Performance Overlay’ switch is turned on and the user closes that window, the DevTools Controller calls the setState() from its property variable, _state. See the second screenshot above. The third screenshot above highlights where that variable is initialized and what it is assigned to. It’s assigned the app’s State object (the first State object), and it’s assigned in the controller’s initState() function. Now, guess where that initState() function is called.
It's called by the StateX object, _StockSettingsState, in its own initState() function. Remember, the DevTools controller was passed to that StateX object’s parent class constructor. Not only does the controller now have access to that StateX object and all its capabilities, but that StateX object now has access to that controller…and all its functions.
As you know, in Flutter, when a State object is to be displayed for the first time (i.e. before it calls its build() function for the first time) its initState() function is first called. The same, of course, is true for any StateX object in the Fluttery Framework. When a StateX object calls its initState() function, any StateXController(s) taken in by that time will have their own initState() functions called as well. Easy peasy. These SOC’s (State Object Controllers) share some of the same functions as their associated StateX object making for more efficient development frankly. That’ll be demonstrated in articles to come.
See how this all comes together? Notice how this framework behaves like Flutter because it was written to behave like Flutter? When it comes to State Management, things appear to be working out just fine, don’t they?
State and Control
And that’s about it. It’s those two classes, StateX and StateXController, that make up the core of the Fluttery Framework. Any additional classes introduced to you in this framework will be a subclass of one of these two classes— one of which, of course, is the subclass of Flutter’s own State class.
In The Beginning
An example of this is seen in how a typical Flutter app starts up when using the Fluttery Framework. Let’s finish this first article in the series by examining the Stocks example app’s main.dart file. As you can see in the screenshot below, there really isn’t much to it. That’s by design. The remaining source code is safely inside the src
folder. The runapp() function only requires one lone Widget as a parameter. The app really begins with that one lone Widget called, MyApp.
The StatefulWidget, MyApp, has a parent class called, AppStatefulWidget. Tap on the first screenshot below for a closer look. Pretty straightforward. It’s the widget I recommend you pass to the runApp() function because it then calls its createAppState() function to create the Fluttery Framework’s AppState object. That’s the ‘first’ State object for your Flutter app and, of course, is a subclass of the StateX class. You can see in the second screenshot below, it has a named parameter called, controller.
Keeping it Flutter.
The third screenshot is that of the AppStocks class — a subclass of the AppController class which, in turn, is a subclass of the class, StateXController. Both the AppState and AppController class have their specialized roles to play when making your Flutter app development that much easier and that much more productive. I mean, tap on the caption under the second screenshot below, and it’ll take you to the Fluttery Framework’s GitHub repository. There, you’ll see how many parameters the AppState class has available to you to define the ‘look and feel’ of your next Flutter app. The source code is all documented. You can figure it out. But don’t worry, we’re just getting started with this series of articles.
State My Admittance
Finally, as you may have long realized by now, I really shouldn’t be explicitly comparing this framework to the Dart packages in that list above. Those are library packages simply offering an approach to State Management, this is much more…it’s a Framework.
The classes, StateX and StateXController, that make up the core of the Fluttery Framework, would be a more accurate comparison to that list. I wrote the state_extended
package to more effectively and more efficiently implement State Management with Flutter; like Flutter. It just happens that this framework uses it as well.
It’s the Fluttery Framework that implements the rest. That is, it implements things that should come with your app in the first place — standard functions and features to be found in any production release, Frameworks are to assist developers in building their apps — make development that much faster and that much easier. Frameworks do the ‘heavy lifting’ and provide standard capabilities reliably and consistently so the developer doesn’t have to every time. They’re to provide aspects of development we developers are guilty of not considering as much as we should. Error handling comes to mind. Unfortunately, when it comes to error handling, our priority is to write code that works —we tend not to consider what should happen if something goes wrong. This series will address all of that in time.
Until then, I invite you to download the example app, Stocks, and take the Flutter Framework for a test drive. ‘Keeping it clean,’ ‘Keeping it simple’ and ‘Keeping it Flutter’ has made my projects adaptive, scalable, and maintainable. True, there are a lot of Flutter developers out there using the top-three State Management library packages up on that list.
I can only assume they just don’t know about this framework yet. ;)
Cheers.