Why I refactored my Flutter app not once, but three times

In this article I’m going to point you to a few mistakes I made while I worked on a Flutter app, and the reasons why I had to rewrite it three times, to finally be satisfied with the result. Please not that this is my personal experience, and my personal opinion on the used packages and methods.

Two years ago, me a friend of mine came up with an app idea – a dating app for a niche market. At that time Flutter was all over the news and I was excited to try it out. Coming from a full stack web development background (PHP, JavaScript) I wanted to expand my skills and try something new. So I decided to use Flutter for the mobile app, and NodeJS for the backend services.

https://diadating.com/ It’s a dating app for people living abroad.

Initial attempt – Bloc-Pattern

After I’ve laid out the screens for the app, it was time for the business logic. At that time the Bloc pattern was very popular and recommended by the community. I tried to wrap my head around the best practices of the pattern and created my own “architecture” based on the famous BlocBase approach. Unfortunately, I couldn’t find the original article anymore. But the basic idea was that you create a BlocBase class which extends the ChangeNotifier and updates the UI when notifyListeners() is called. This helped me to separate my business logic from the UI from the beginning on, but since it was something I created from scratch and without much knowledge about Dart and flutter, as you could imagine, it was quite buggy.

1st rewrite – Provider package

After I spent some months with my initial attempt, I decide to do research again, and see what’s happening in the community regarding separating business logic from the UI and state management. The new kid on the block was provider, which was recommended even by the Flutter devs themselves.

So I started to read the docs and refactoring my app for the first time. Needless to say, provider was much easier and less error-prone to work with, than my self-hacked-architecture. But…

… as my app began to grow in features, I quickly found myself in a hell of boilerplate code. Especially Consumer() , StreamProvider() and FutureProvider() widgets were all over the place. I hated the fact, that when I took a break from the project, came back to it, I couldn’t get back into the code very easy.

2nd rewrite – Stacked architecture and GetIt

Again, weeks went by while I was refactoring my app from the self-hacked architecture to provider, I decided to see what’s going on in the Flutter community and found the stacked package. As you may’ve guessed it, I gave it a try, and wow… I quickly found myself very comfortable with ViewModelBuilder.reactive() which updates the whole UI. And for partial UI updates I could simpyl use MyWidget extends ViewModelWidget<FooModel> instead of the Consumer() boilerplate-hell of provider. I was very happy with that package, and I could get most of my work done, while keeping my business logic separate from the UI. Using the GetIt I package, I could easily access all data thatneeded to be initialized and modified during app usage.

So, as I implemented more and more features, like notifications, overlays, FCMs, etc, I realized another problem. My `pubspec.yaml` got flooded with packages. And I didn’t like that either. I didn’t want my app to depend on multiple packages. I wanted it as simplified as possible.

3rd and final rewrite – GetX

While I was pretty satisfied with the stacked architecture, I was curious what was going on in the Flutter community. And the folks didn’t sleep at all 🙂 I stumbled across the GetX package, which, while reading the docs, looked very promising.

In the meanwhile, I had another idea for an app (https://blitzcoin.biz, you can sell your stuff for crypto curency), and I decided to start that fresh new project with GetX, since this new app shared some similarities with my dating app. While reading the docs, I found out that GetX included everything that GetIt and stacked already provided, and much more. Dependency injection, routes, observables, snackbars, overlays… literally everything you’d need for an app, you can implement without hassle and especially without boilerplate.

I was able to get a ready to use app within a few weeks. I guess I can call myself Flutter Senior Developer now 🙂 It took me actually two months to build the mobile app (for Android and iOS) and the server side code with NodeJs.

Eventually, I came back to my dating app and rewrote everything using GetX, and I’m more than happy with it.

I hope you may find this article helpful for your next project.

What’s your go-to architecture in Flutter. Let me know in the comments.