MVVM Architecture Simplified - Flutter Recommendation

Flutter released documentation about their recommendation for Architecting your application. It has been met with.....mixed feelings.

Architecture diagram

In this article, we review Flutter’s recommendation for architecting your app.

Flutter documentation showing mixed community reactions to the new architecture guidelines

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

Official Flutter MVVM Architecture diagram showing UI and Data layer separation

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

Flutter documentation excerpt highlighting View responsibilities and UI-specific logic

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

Documentation screenshot showing ViewModel's role in handling business logic and state management

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

Diagram illustrating the Model layer components including Repository and Service

”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

Example architecture diagram showing user information flow from Firebase through MVVM layers

To illustrate, let’s take a user’s information coming from Firebase services:

  1. HomeView: The main page of the app displaying the username in the AppBar.
  2. HomeViewModel: Contains all business logic for HomeView and exposes a ValueNotifier<UserData> for the AppBar to listen to. It may also include functions like updateUsername.
  3. UserRepository: Does not store data but provides functions like streamUserData, delivering real-time updates. It relies on the AuthenticationService and DatabaseService to fetch authentication states and user data, respectively.
  4. Services: Abstract API calls; for example, AuthenticationService might use Firebase Auth, while DatabaseService might use Firestore.

Diagram demonstrating the flexibility of MVVM when switching backend services

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

Course architecture diagram showing the Data Source naming convention

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

Diagram highlighting the gap in Flutter's MVVM regarding app-wide state management

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

ChatGPT conversation about Flutter's handling of 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

Summary diagram of Flutter MVVM architecture with noted improvements needed

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.

Course thumbnail

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.