Latest news about Bitcoin and all cryptocurrencies. Your daily crypto news habit.
You know what I donât like about Flutter? Very little. However, I did, have to get use to reading the long vertical lists of parameters. Most times, they werenât just parameters, theyâre a list of anonymous functions being passed as parameters which made it that much harder to read. And Man! At times, there is a lot of clutter! A lot of Flutter Clutter!
Of course, one can adapt. It does has its merits, but I decided to clean it up a bit. Below is a âbefore and afterâ picture. What do you think?
Original ContactDetailsPage vs. New ContactDetailsPage
By Example
Iâm using the repo., contacts_service, as an example. I arbitrarily picked it. Iâm not picking on those particular developers or anything. As it happens, it itself demonstrates the use of the contacts_service plugin, but my version is not some much about the âpluginâ but more about the âlook and feelâ. More about organization really. More about the MVC design pattern specifically.
So, do you like it? What do you see? I see clean. I can readily see the âdataâ is coming from static references in a class called, Contacts. Itâs coming from the Contact classâ âedit referenceâ specifically. This is the appâs edit screen after all, and so we can see that the class, Contact, is in edit mode! Below is a closer look.
You can see, for example, the AppBar.title property below is getting its data from Contactâs displayName reference. You know that the AppBarâs title property accepts a Widget, and so youâll guess correctly that the item âContacts.edit.displayName.textâ therefore returns a Text Widget. Clean.
MVC is in play
Of all my articles, the most popular has been Flutter + MVC at Last! so far. It talks about implementing the MVC design pattern in Flutter, and youâll quickly see that MVC is in play here as well. Letâs look at the Contacts class.
If youâre familiar with my MVC implementation in Flutter, youâll realize that the class, Contacts, is a Controller in the MVC design as it extends the class, ControllerMVC. You can also see it implements a static factory: Item 1 in Joshua Blochâs now renowned 2001 original publication, Effective Java. You see it imports the class, ContactsServiceâââthe Model part of this app.
Finally, you may have guessed that possibly everything referenced in this class is static (in keeping with Item 22 of Joshua Blochâs Effective Java 2nd ed.), and again, youâd be right.
MVC Inside and Out
Even the directory structure of the app reflects the MVC approach taken when this app was developed. Following a design pattern (any design pattern) provides a guideline, a structure, on how you organize your logic, how you organize your codeâââeven how you organize your files and folders.
Remaining consistent and studious to that structure, for example, allows a âturn overâ of developers to âhit the ground runningâ when going from one project to another. For example, at a glance, they can see below where and what makes up âthe Viewâ, âthe Controllerâ, and âthe Modelâ for this particular project.
Iâve taken the original repo. and organized it in this chosen fashion. I suspect a developer not even familiar with MVC could come to understand âwhere everything livesâ in a reasonably short time. Good design patterns allow for that.
A follow-up article detailing this directory structure is on my âto doâ list.
This projectâs directory structure and its contents
Get it? Got it. Good!
Now, go back up and look at that last getter in the class, Contacts. Itâs called, edit, and it references a âlibrary privateâ variable that, in turn, references the instantiated class, ContactEdit. Remember that getter? Youâve see it before. Itâs Contact in edit mode! Thereâs two more classes: ContactList and ContactAdd. See where Iâm going with this?
You may have guessed thereâs three things here; three âmodesâ to this app. If youâve guessed thereâs three screens in this app: One for adding Contacts, one for editing Contacts and one for listing Contacts. Again, youâd be right.
One From Another
Letâs start from the end. Letâs look at the class, ContactAdd. Note, however, youâll discover it extends from the class, ContactEdit. Weâll then look at that class which, as it happens, extends the class, ContactList. Weâll then look at that, which extends yet another class called ContactFields. Weâll get to them all soon enough, but first, the class that helps âaddâ a Contact in the app.
It Adds Up.
Looking at the class above, you see that indeed this class, ContactAdd, extends the class, ContactEdit. You can see itâs not a very big class but does a lot of interesting things. Firstly, it optionally takes in an âContactâ object in its first method called init(). It then assigns values to two properties called phone and email. Since theyâre not defined here in this class, we can assume theyâre defined in itâs parent class or in another inherited class up the hierarchy. You can see that the init() method calls its parentâs init() method passing in that Contact objectâŠif any.
Thereâs a âlibrary privateâ variable assigned a class called PostalAddress. Thereâs a GlobalKey being provided by a getter called formKey, and thereâs a method called onPressed.
Now thereâs some details Iâve missed, but what I really want you to look at now is how this class is then utilized in the âAdd Contactâ screen for this app.
Look for the âContacts.addâ getter in all the code below. Iâll wait here. (Thereâs little red arrows below to help you out. Itâs not a test after all.) See how the properties and methods found in the class, ContactAdd, will now make sense when you see when are where theyâre applied below.
It Does Add Up!
The âAdd Contactâ screen needs a âform keyâ for its form. Well, where does it get that form key from? Take a look back at the ContactAdd class, and youâll readily see where that form key is to come from. Clean.
When the FlatButton widgetâs onPressed method is called (when a user presses the screenâs âsaveâ button) what method are you to call? Again, looking back at the ContactAdd class, Iâd say youâre to call its very own âonPressedâ method. This approach has a âbigger purpose.â You can see the build() function actually dictates the api to be used by the Controller, no?
Another article detailing this is also on my âto doâ list. That list is getting long.
Look at the data to be displayed when adding a new Contact. Can you readily guess what data is to be entered? Bet you can! (Hint: givenName, middleName, familyName, etc.) You can also readily see that the data is to be entered in a list of TextFormField widgets as well. Letâs look at the original screen below. See how the âdataâ and âinterfaceâ are not separated as much?
Edit AÂ Contact
What have we got next? Next, weâve got editing a Contact. We can readily see that the class, ContactEdit, extends the class ContactList. What does one usually do with a Contact in a Contact list? We usually add, edit and delete a Contact, donât we. We may even âundeleteâ a Contact if we change our minds. Look below. What do you see?
You can see the class, ContactEdit, calls static methods from the class, ContactService, (the Modal aspect of the app) to add a contact, to delete a contact, and to âundeleteâ a contact. You can see that the contact object passed to these methods is first changed into a âmapâ object. You also see the contact object parameter is optional, and if null, assigns the âlibrary privateâ variable, _contact. Note, that variable is from the parent class, ContactList.
Contact!
The Contact class has the getter, toMap. As you see below, it also has a named constructor called Contact.fromMap. You can guess what that does. You donât see them here, but that constructor assigns the map entries to a list of setters named after the Contactâs field names. However, you do see the list of âlibrary privateâ variables being assigned by those setters. Finally, you see the getter, toMap, that converts the Contactâs properties back into a Map. Youâll guess correctly that the âbackendâ deals directly with Map objects. Clean.
List them Contacts
The next class is the parent class of the previous two. It has a lone method called init(). You can see a mess of âlibrary privateâ variables being assigned a variety of âFieldâ classes. All those variables are obviously defined from the parent class, ContactFields. A ânewâ Contact object is created if no Contact object is passed to the init() method. Note, the object is assigned to that variable, _contact, we saw in the previous class, ContactEdit.
Whatâs Your Field?
Letâs take a quick peek at one of those âFieldâ classes. The first one listed above is the class, DisplayName. This one is very much like the others, but like the others, it has to be specific and provide its particular field name, displayName. Note, the variable, value, is from the parent class, Field.
Note, onSave() is called when you save a Contact, for example, in the AddContactPage under the method, _formKey.currentState.save(). While the circleAvatar is, of course, found in the main screen, ContactListPage.
A Field of Contacts
The first class in this hierarchy is the last class weâll look at, ContactFields. You have seen how each class âbuilds upon the previous oneâ in one degree or another. Now what does this class provide? It provides the the âfieldâ variables of the type, Field, along with their associated getters and setters. See below.
List Your Contacts
Below is the build function for the first or âmainâ screen of this app. Those familiar with my implementation of MVC in Flutter, know I consider the build() function of the Widget for the âmainâ screen of an app (the build() function of any Widget actually) to be âthe Viewâ in the MVC implementation. Remember?
For this app, any data displayed in âthe Viewâ is accessed through the Controller. So in this case, Contacts is the controller for this app. Below, anywhere you see the word âcontactsâ, you know its value(s) are being drawn out of the Controller. You canât see it here, for example, but the âprivateâ variable, _contacts, gets its values from a method found in the Controller: Contacts.getContacts()
ContactListPage Build() function is the appâs View
Iâd put up its original version, but youâll get lost in the code. Go look at its original Github if you want to make a comparison. Note, I did put in a Dissmissible widget (red arrow) in my version so to easily delete contacts. The original doesnât have a means to delete contacts, and in my version you can see at a glance, what field is displayed and âdeletedâ with a swipe!
Whereâs this Dismissible Discerned?
I may be getting ahead of myself a bit here, but that red arrow is introducing you to a very important approach applied here: The Controller is not only determining âwhatâ is displayed, but âwhatâ you can do with it. To a degree, this approach has the Controller take up what would be the Viewâs job and presents the data in a certain fashion (i.e. in a TextFormField, in a Text, and or in a Dismissible.)
As you saw in the class, ContactFields, there are a mess of âFieldâ classes being defined. It is in this class, Field, where you will find the method, onDissmissible().
The Getter Gets It
The method above actually calls the getter, dismissible. It is the getter that returns the desired Widget (in this case, a Dismissible) to the variable, newWidget listed above.
Talk About Flutter Clutter
As you see above, thereâs a lot going on. Libraries are designed to make the lives of developers that much easier, but as a consequence, they tend to get messy themselves (having a lot going on in the background.) In this case, all the parameters associated with the Widget, Dissimissible, are made available to the user to use⊠or not. If not, the library supplies other values or functions. Doing so allows for options, and developers love options.
For example, doing so allows the us to âclean upâ the code a little bit in the example above (beside the big red arrow.) Note, that example has two anonymous functions being passed to the function, onDismissible. One for the named parameter, child, and another the named parameter, dismissed.
I mean, this whole exercise was to reduce the practice of passing anonymous functions as parameters, remember? WellâŠletâs do that. Boom!
ContactListPage build()Â function
Whereâd Everybody Go??
Pictured above is the same build() function first displayed with the method, onDismissible. It was used with its named parameters: child and dismissed, but now theyâre all gone?! Replaced now with the item, âContacts.list.displayName.dissmissibleâ. Where did they go? Take a guess. If you guessed theyâre now in the class, DisplayName, accessed by the getter, displayName, youâd be right.
The class, DisplayName, first introduced to you now has two new implemented methods. Each overriding methods from the parent class, Field: onDismissed() and onChild(). That particular âlogicâ is now embedded on the âController side.â
MVC Means Manageability
It results in the âseparation of work.â Picture a team of developers were working on this app, and one developer was assigned the âContact Dataâ aspect of the app. Heâs not even given access to the build() functions! He does his work in the Controller as itâs the Controllerâs responsibly to provide the data to the View (i.e. the View can âtalk toâ the Controller). Thus, heâs only to provide the API (the public properties and functions) to the âUIâ team needed to access the âContact Data.â No problem. In this particular case for example, he gives them this: âContacts.list.displayName.dissmissibleâ.
Done.
It took a little more coding, but there you are. As it is, I prefer the former implementation over this one. Itâs just a small little app, and I feel the separation of logic need not be that pronounced. Regardless, the point is youâve got options, and we developers love options. Right?
The Field Class
So letâs take a further look at this class, Field. As you may have guessed by now. Itâs a library Iâve created to make my life as a developer that much easier. It makes my code (code in my build() functions) that much cleaner. When the Controller is to provide a specific data field, it can do so with a Widget most appropriate for the situation. It can be a TextFormField, a Text, a ListTile, a CheckBox, and a few others. The list of Widgets is finite, but is growing. Like any good library file, it does a lot of the grunt work for you.
The Irony
Look at me. I started this article maybe complaining a little bit about the list of parameters found in Flutter, and I end up making a class library accepting some 77 parameters. And thereâs likely going to be more to come! Hilarious!
The Point To All This
Anyway, do you see why I did that? On your next project, youâll have a data field from a database, and you are to display that data field in a TextFormField, a ListTile, a CircleAvatar, and maybe even in a CheckBox. On top of all that a Dismissible is to be implemented so that data field can be deleted with a swipe of a finger on some other screen down the line.
The point is, define one Field object passing all the necessary parameters for all those Widgets, and youâre done. Get it? You now have a Field object you can apply to a number of screens throughout your app. What do you think?
Widgets? How Many Widgets?
As of this writing, the Field class accommodates the following Widgets. Again, more are likely to be added.
TextFormFieldTextRichTextListTileCheckBoxListTileCircleAvatarDismissibleCheckBox
So Whatâs The Real Point To All This?
So, you can deduce that the Field class is still a work in progress. Itâs in a file under the directory, Utils , but you can see itâs not alone. You see, the Field class is merely in a utility file called Fields.dart inside a even bigger repository. One that holds my next package release, mvc_application.
The Bigger Picture
In my development, Iâve slowly but surely been making my own little âapplication frameworkâ so to make my life easier with each subsequent project. Developers tend to do that of courseâââbuild up their toolkit.
With MVC_Pattern comes MVC_Application
I was pleasantly surprised with the release of the package, mvc_pattern. This package applied the 40-year old MVC design pattern to your Flutter app, and it received a receptive response when released. I saw a need, and as itâs my chosen design pattern for most of my apps, it was nice to see many still appreciate the âgrandfather of design patterns.â
As time went on, me working away, my âtoolkitâ has grown. Now the intent is to release my current framework, mvc_application, as a package. It wonât be tomorrow, but soon. As it is, it simply works on top of the mvc_pattern package, but includes a number of other libraries Iâve written and use in development. This includes some Iâve already publicly released and documented in past articles:
Whatâs My End Game
So, whatâs my end game to all this? As it stands, Iâm just contributing to this fledgling Flutter community. Use it or not. Take what you want from it or not. Admittedly, in the end, it doesn't hurt to build up oneâs profile a little bit. After all, this is my how I make a living. So what does the future have in store? Again, Iâm looking to release the package, mvc_application. After that? Oh I donât knowâŠ.mvc_enterprise?
Cheers.
Clean up all the Flutter! was originally published in Hacker Noon on Medium, where people are continuing the conversation by highlighting and responding to this story.
Disclaimer
The views and opinions expressed in this article are solely those of the authors and do not reflect the views of Bitcoin Insider. Every investment and trading move involves risk - this is especially true for cryptocurrencies given their volatility. We strongly advise our readers to conduct their own research when making a decision.