Flutter MVVM architecture using Dependency Injection (DI) + State Management + Repository Pattern

César Ferreira
3 min readFeb 4, 2020

When Joe li and I started building NIGHT NIGHT, an app that teaches parents how to make their kids fall asleep by themselves. Me, being the solo developer on this team and coming from a native Android developer background I pondered if I should build it twice using kotlin and learn swift for the iOS version or if I should go for a multi platform solution. Since there was a lot of buzz around flutter, I wanted to see what the fuss was all about.

After only a few hours of doing flutter tutorials, experimenting and watching Flutter Widget of the Week youtube playlist, my speed building UI was already faster and way more enjoyable than native android and I have ~10 years of android experience. That just blew my mind. I was convinced to build this app on it. One month later we released it on the app store and we’re currently getting a great amount of sales.

Here’s my approach to the architecture, for simplification purposes let’s build a simple app that reacts to a login / logout button:

Dependency Injection + State Management

It’s 2020 and if you’re not using a dependency injection library, you might be wasting precious time managing things that could be managed for you. After trying the top 3 recommended libraries for this purpose, I ended up going for provider, a mixture between dependency injection and state management that is pretty straight forward, not very verbose and gets the job done quite well.

User repository

Let’s start with our repository, as you can see on the code bellow, we can login, logout and get the current logged in user’s name, if the user kills the app and opens it again it will remember if you’re logged in or not so the UI can change accordingly.

I used https://pub.dev/packages/shared_preferences to read/write to SharedPreferences/NSUserDefaults.

user.repository.dart

User View Model

This class separates ownership of view data and logic from lifecycle-bound widgets. It talks to the repositories and holds state for your UI to react to.

user.viewmodel.dart

The Screen

Simple UI with a login/logout button and a centered text view that change according to the ViewModel state.

home.screen.dart

And finally…

Lets make our main()be asyncso we can initialize all of our components that need to run non synchronous code.

main.dart

The gift that keeps on giving…

After I started the project, the flutter team released two new features that allowed me, without changing any code, compile to both macOS and web:

macOS (left), web (right)

All the code can be found here: https://github.com/cesarferreira/flutter-architecture-example

Thanks

I would love to know what do you think and if you do something in a different way. Also it would be awesome if you click the little clap icon and share the article so more people would benefit from it.

If you are interested in more tech related topics, please check my other articles, follow me on Twitter or check my GitHub projects.

--

--

César Ferreira

Senior Android Developer, currently working as a Tech Lead @GlueHome. More on me @ https://cesarferreira.com