In this article, we review Flutter’s recommendation for architecting your app.
It has been six years since Flutter was initially released, and the Flutter team has finally published a guide on how to architect your applications.
To put it lightly, it has been met with mixed feelings.
I decided to go through the guide line-by-line to gain a complete understanding of it.
Key Visual of Flutter MVVM Architecture
This is the key visual for understanding the Flutter MVVM Architecture. It is separated into two sections: the UI and the Data layer. The View represents the actual UI—the elements users see and interact with. Each View has a 1-to-1 relationship with a ViewModel, which handles all the business logic.
The Role of the View
In other words, your View should not perform any logic unless it is directly tied to the UI. According to the Flutter documentation, the only logic that can reside in a View includes:
- Simple if-statements to show and hide widgets
- Animation logic
- Layout logic
- Simple routing logic
The Role of the ViewModel
The ViewModel handles all other logic, which can directly or indirectly manipulate the data it holds. Additionally, the ViewModel must expose a Listenable
so the View can update whenever its dependent data changes. While there are several ways to achieve this, my favorite is ValueNotifier
. We’ll explore that further shortly.
The Role of the Model
”M” stands for Model, representing the data outside the View. Flutter refers to this as the data layer, which includes two components: the Repository and the Service.
- Repository: The single source of truth for the data used within your application.
- Service: Abstracts API endpoints for the Repository to use.
Example: User Information from Firebase
To illustrate, let’s take a user’s information coming from Firebase services:
- HomeView: The main page of the app displaying the username in the
AppBar
. - HomeViewModel: Contains all business logic for
HomeView
and exposes aValueNotifier<UserData>
for theAppBar
to listen to. It may also include functions likeupdateUsername
. - UserRepository: Does not store data but provides functions like
streamUserData
, delivering real-time updates. It relies on theAuthenticationService
andDatabaseService
to fetch authentication states and user data, respectively. - Services: Abstract API calls; for example,
AuthenticationService
might use Firebase Auth, whileDatabaseService
might use Firestore.
This structure might seem cumbersome, but it provides immense benefits. For instance, if you want to switch backend services from Firebase to Appwrite or Supabase, you only need to update two files in your application. The rest of the architecture remains unaffected.
Why Good Architecture Matters
A well-designed architecture ensures maintainable code and enables effective teamwork. It is crucial for scalability and adaptability.
Our Approach
The architecture we teach in our course is quite similar, with one notable naming difference. What Flutter calls a “Service,” we refer to as a “Data Source.” Our approach also includes a “Service” layer, but it is used for app-wide state management.
The Missing Piece: App-Wide State
Flutter’s MVVM documentation does not explicitly address app-wide state. The closest reference is a section discussing a LogoutView
used in multiple parts of an app. However, the documentation repeatedly states that each ViewModel should be tied to one View. This approach can be limiting.
For example:
- What if you want a differently styled logout button?
- What if you need logout functionality for a “Switch Account” action?
Addressing App-Wide State
I even tried consulting ChatGPT about how Flutter handles app-wide state. Unfortunately, it hallucinated a “Service” class similar to the one we use in our approach to MVVM.
Final Thoughts
The Flutter MVVM guide provides solid principles but lacks clarity around app-wide state management. Names are less important than sound architecture, but this oversight should be addressed in future updates.
Want to learn Flutter?
We teach you all you need to confidently build apps at hungrimind.com/learn/flutter
Our course is designed for adaptability. Once the debate around this architecture settles, we may adjust our naming conventions if it makes sense. However, the principles will remain the same, with the addition of app-wide state for better flexibility and functionality.
YouTube Video
Get articles right in your inbox
No spam, unsubscribe anytime. We treat your inbox with respect.