First of all, I started off with reading Effective Dart guidelines, not sure if it’s the best guideline to follow but so if you know any better — feel free to share in the comments.
Last time I focused on creating my first widget — a glass filled with a water. This time I decided to add to my application a few more screens — one is not enough obviously. Hamburger menu is not an option for such a simple app and I think it’s getting old and boring and the trend is back to bottom tabs.
Since the choice for simple and easy, I quickly added a
BottomNavigationBarto my Home/Dashboard view. By the way… I really like the tips from IDE about missing required parameters etc., there is no need to worry (so far) which constructor to use and can just use the basic one and add required parameters and optional as needed since the tip shows all possible options. For example, for
BottomNavigationBar it told me that there MUST be at least two items- quite obvious (since why would we want to add that otherwise) but there is no such need with
UITabBarControllerso might be confusing for iOS Developers. I did not like that
BottomNavigationBarItemrequired title parameter though, why can not I add an item with just an image? What I do not like about this component though is that it changes its style automatically depending on how many items are there — if more than 3 then it changes its style and that also means colors etc. Spent some time before noticing that and had issues while styling it. Other than that it was quite simple.
Added also few more buttons here and there (including my own widget — expandable floating action button which is collapsed at the start and when tapped shows other floating buttons with some actions).
As my app’s code grows I noticed it is getting harder and harder to pass data between widgets and manage app’s state at all. Since I already know a little bit how Dart and Flutter “work” it was the best time (before the app is too big for refactor or is this already too late?) to choose the best fitting architecture pattern 👏. The “google and read marathon” has begun 📚. I kept reading, reading and reading and could not make my mind — which architecture to choose — Redux, MVI/Streams, Scoped Model or maybe something else? Seems like there is no “golden pattern” to choose. Here I give two useful links if you want the description of each architecture, check out those two links: this and this one. After all that reading I decided to give Redux architecture a try. It seems quite easy to implement and understand. What are the three principles of Redux?
- Single source of truth
- State is read-only
- Changes are made with pure functions
Let’s lean on the first point — a single source of truth — I am just not sure if I understand it correctly. Does it mean I can not (or well, rather “should now”) have multiple stores in my app (note: a store is an object that simply holds state tree — to simplify it you can think of it as data/values — of a whole application)? I think I kinda do not like such approach although since it is a quite small app it will be a good fit for me anyway. What do you guys think about Redux though? Do you think it would be okay to create multiple stores?
Anyway, I refactored my Homepage using Redux architecture pattern and it might feel confusing at the beginning but it didn’t really take me longer than a few hours to understand how it works — I hope I use it properly 😅. Might write an article about Redux in Flutter some time although there is already a nice one (and more can be found googling) so not sure about that yet. The one that helped me understand Redux is written by Paulina Szklarska and can be found here. Sadly the code embedded in the article is a little bit out of sync (outdated) with the code in sample repository on GitHub so it might be confusing a bit.
When it comes to (big) data storing in Flutter probably the best choice is going for sqflite. Writing a plugin to handle iOS’s CoreData would be too overwhelming I guess and simply… not needed since sqflite is good enough in my opinion.
In my app, I will (for now) need simple table that stores added water (drinks) with a date and time. Also, need to store user’s settings (daily and current goal) — for that I am going to use shared_preferences, plugin made by Flutter Team 👌.
I started with implementing Shared Preferences but first I needed a screen where I can save those values — quickly (developing in Flutter is indeed, REALLY quick) added Settings page (which I will improve later on) with just a one save button that randomly sets up the Daily Goal. I was a little bit surprised that Shared Preferenced are saved and loaded asynchronously and it was kind of a challenge to integrate it with a Redux pattern — had to use middlewares and it took me few hours to set them up properly. Still, I have to write a handler to catch error exception while loading from preferences but once everything is configured I am pretty sure it will be a piece of cake to do that one.
Next goal was to add a database for storing entries of added drinks (note: Google still does not know what sqflite is and keep suggesting SQLite 🌝). Spent some time to implement it… way too much. I have written a
DatabaseManager class that uses generic methods to insert and fetch data from database
and while inserting to model to the database I was getting an error about the incorrect type of map. Which was damn confusing since the type was correct. I just messed up columns (tried to insert 2 instead of 3) and noticed it maybe after like a 2 hours 🙁 Also I hope
sqflite will be improved later on, it is not that friendly to use in my opinion — it could provide some configurable default manager which will have a method to fetch/insert model of given type (which extends abstract class of database model) from certain table or something like that. I am pretty sure the developer-experience could be improved here. I think the hardest part here was to integrate it with the Redux pattern, took me a while but finally everything works (I hope so 😅).
Slowly getting closer and closer to finish implementing basic functions for my water drinking tracking app and probably the major refactor will start 😋. I plan to redesign my entire app since I feel like the Top+Bottom navigations bars do not really fit here (my wife’s suggestion and I agree with that ❤️) and gonna try to design it using Gravity Designer (instead of Adobe XD) this time — or maybe if you are by any change a designer and want to make some nice design for the app you can let me know and contact me by email if possible 📨.
Just one thing that is not a good thing… but I can not blame Flutter for that, it is still in beta and it changes a lot, right? So many guides and tutorials are just out of date and have to look for updated one or just check changelogs of plugins that you are using and apply the changes.
Also, I am more and more willing to share the code so in the last part of the series I will share the code (or part of it — most interesting ones).
Btw. The import suggestions are damn awesome. So far it always knew what import should I add. It makes adding import so much easier since typing the whole path to file to import it is a little bit boring. I really love that and I wish Xcode had for Objective-C such feature as well — for Swift, it’s not really needed although it should suggest which framework should I import.