Landing Page for the “MVC Flutter Framework” video series on YouTube.
MVC in Flutter has come a long way. From October of 2018, it continued to evolve and grow into an established approach for developing apps in Flutter.
It was a conscious effort to incorporate the MVC design pattern into the existing Flutter framework taking advantage of all that is Flutter while almost seamlessly applying the Model-View-Controller approach. If you know Flutter, you can use the MVC framework showcased here. If you know MVC, you’ll learn how to work with Flutter.
The framework does not blatantly ‘sit-on-top’ of the Flutter framework — it works with Flutter to provide a standard set of functions and features as well as a structured approach to organize your source code and accelerate more efficient software development. It’s true — and it’s all available in a self-contained Dart package, mvc_application.
Primarily, this article is to serve as a supplement to the series of YouTube videos that I’m working on to introduce the MVC Flutter framework to developers. Each video will be accessible here, and this article will likely include further information regarding each video’s topic. Depending on the extent of the information, separate articles altogether may be necessary for a particular video. In such a case, a link to that article will be available here.
This will be a living document including additional articles and information as each video is released — further explaining how the MVC design pattern is implemented in Flutter, and how you can take advantage of that fact.
Intro. to the MVC Flutter Framework
The first video will introduce the MVC Flutter Framework by implementing it with the proverbial ‘Counter App.’ It’s the app first displayed to you when you ever create a new Flutter project. This video conveys the more immediate benefits of following the MVC design pattern when developing software in Flutter. Note, the source code for this series is readily accessible on GitHub: counter_app
You’ll note in the video, the one constant characteristic presented is the separation of the app’s data, from its interface and from its event handling: Model-View-Controller. How these three components ‘talk to’ each other, however, can vary depending upon the sheer size of the app in regards to the number of API calls necessary to run it. In other words, the MVC design pattern can adapt to reflect such necessities allowing for scaling and maintainability:
There are Many Views To Everything
It may not be readily apparent in the video, but a Controller could be registered with or assigned to any number of Views (or StateMVC objects). The Controller has ready access to ‘the last’ State object it’s been assigned to. When that screen closes (ie. that State object terminates), the Controller regains access to the previous ‘View’ it was assigned to. This capability, for example, allows for one Controller to contain the sustained business logic for the whole app in one location — in one class. However, convey that logic in any number of different ways in the form of different interfaces.
Of course, in this implementation of MVC, a View can have any number of Controllers assigned to it — avoiding the ‘Controller Bloating’ cited as a common criticism of the MVC design pattern. Each Controller could then, for example, be dedicated to a particular responsibly independent of the remaining Controllers and the rest of the application. This encourages modular development of the software.
Further, since a registered Controller has access to its ‘current’ State object, it then has access to the many ‘events’ that may be triggered while the app is running. Those developers coming from the Android platform will recognize this as a common practice when listening for events in the Activity class and its Lifecycle.
initState() — Called exactly once when the State object is first created.
initAsync() — Called exactly once at the app’s startup to initialize any ‘time-consuming’ operations that need to complete for the app can continue.
dispose() — When the State object will never build again. Its terminated.
didChangeAppLifecycleState(AppLifecycleState state) — Called when the system puts the app in the background or returns the app to the foreground.
didUpdateWidget(StatefulWidget oldWidget) — Override this method to respond when the Widget changes (e.g., to start implicit animations).
didChangeDependencies() — When a dependency of this State object changes.
didChangeLocale(Locale locale) — When the system tells the app that the user’s locale has changed.
didChangeMetrics() — When the application’s dimensions change. (i.e. when a phone is rotated.)
onError(FlutterErrorDetails details) — Allows one to define their own Error Handler. The default routine is to dump the error to the console.
reassemble() — Called during hot reload. For example, whenever the application is reassembled during debugging.
deactivate() — When the State object is removed from the Widget tree.
didChangeTextScaleFactor() — When the platform’s text scale factor changes.
didHaveMemoryPressure() — When the system is running low on memory.
didChangeAccessibilityFeatures() — When the system changes the set of active accessibility features.
The MVC Flutter Framework Modular Structure
Additional videos will soon follow…