Logo

dev-resources.site

for different kinds of informations.

Design Pattern in Flutter MVVM

Published at
1/8/2025
Categories
dart
flutter
mobile
programming
Author
sukmarizki04
Categories
4 categories in total
dart
open
flutter
open
mobile
open
programming
open
Author
12 person written this
sukmarizki04
open
Design Pattern in Flutter MVVM

Purpose: The MVVM (Model-View-ViewModel) pattern is used to separate the UI (View) from the business logic and data (Model) in Flutter applications. This separation improves code maintainability, testability, and scalability.
Core Concepts:

Model: Represents the data and business logic.
View: Displays the data and listens to user interactions.
ViewModel: Acts as a mediator between the View and the Model. It handles the presentation logic and exposes data to the View.
Benefits:
Separation of Concerns: Keeps the UI code separate from the business logic.
Testability: Makes it easier to test the business logic and UI separately.
Maintainability: Simplifies the codebase and makes it easier to maintain.
Example Code:
Let’s create a simple counter app using the MVVM pattern.

Step 1: Create the Model


// models/counter_model.dart
class CounterModel {
  int counter;

  CounterModel({this.counter = 0});
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Create the ViewModel

// viewmodels/counter_view_model.dart
import 'package:flutter/material.dart';
import '../models/counter_model.dart';

class CounterViewModel extends ChangeNotifier {
  CounterModel _counterModel = CounterModel();

  int get counter => _counterModel.counter;

  void increment() {
    _counterModel.counter++;
    notifyListeners();
  }

  void decrement() {
    _counterModel.counter--;
    notifyListeners();
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Provide the ViewModel
Wrap your main app widget with a ChangeNotifierProvider:

// main.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'viewmodels/counter_view_model.dart';
import 'views/counter_page.dart';

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => CounterViewModel(),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: CounterPage(),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Create the View
Use the Consumer widget to listen to changes and rebuild the UI:

// views/counter_page.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../viewmodels/counter_view_model.dart';

class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('MVVM Counter'),
      ),
      body: Center(
        child: Consumer<CounterViewModel>(
          builder: (context, counterViewModel, child) {
            return Text(
              'Counter: ${counterViewModel.counter}',
              style: TextStyle(fontSize: 24),
            );
          },
        ),
      ),
      floatingActionButton: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          FloatingActionButton(
            onPressed: () => context.read<CounterViewModel>().increment(),
            child: Icon(Icons.add),
          ),
          SizedBox(height: 8),
          FloatingActionButton(
            onPressed: () => context.read<CounterViewModel>().decrement(),
            child: Icon(Icons.remove),
          ),
        ],
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

In this example, the CounterModel class holds the data. The CounterViewModel class acts as a mediator between the model and the UI, handling the presentation logic. The CounterPage widget is the View, which uses the CounterViewModel to display and interact with the counter data.

By using the MVVM pattern, we achieve a clean separation of concerns, making our code more maintainable and testable.

flutter Article's
30 articles in total
Favicon
Flutter vs React Native in 2025: A Comprehensive Comparison
Favicon
Building a Cross-Platform Food Ordering App with Flutter
Favicon
Deploying Flutter Web Apps using Globe.dev
Favicon
Flutter App, Speech to Text and Text to Speech 🐣
Favicon
Journey to Clean Architecture: Wrestling with a 10k Line Flutter Legacy Codebase
Favicon
Building the 'One of a Kind' Ultimate Mobile App Framework. Seeking exceptional engineers to join the journey.
Favicon
Why Should You Develop a Native Android App Over Flutter?
Favicon
Flutter Development for Low end PCs
Favicon
5 Essential Flutter Widgets Every Developer Should Master
Favicon
Mastering Nested Navigation in Flutter with `go_router` and a Bottom Nav Bar
Favicon
Flutter for Beginners: From Installation to Your First App
Favicon
Building a Beautiful Login Screen in Flutter: A Complete Guide
Favicon
Flutter Design Pattern Bussines Logic Component (BLOC)
Favicon
Movie X: A Developer’s Dive Into Flutter Project Organization
Favicon
Create Different Type of Flavor on Flutter Application
Favicon
Handling PathAccessException in iOS for File Download
Favicon
Full Stack Development (Mern && Flutter)
Favicon
Common mistakes in Flutter article series
Favicon
Design Pattern in Flutter MVVM
Favicon
7 Ways to Refactor Your Flutter Application
Favicon
is there any good article for custom lint rules in flutter?
Favicon
WebRTC vs Agora Video SDK vs ZegoCloud for Video Calling in Flutter: A Comprehensive Comparison
Favicon
Hassle free flutter Development in Hyprland with Neovim
Favicon
How to Build a CRUD Application Using Flutter & Strapi
Favicon
Flutter vs. React Native: Which mobile framework will you choose in 2025?
Favicon
Understanding ShellRoute in go_router: Managing Shared Layouts Effectively
Favicon
From Chaos to Control: The Day I Learned the Magic of Debouncing in Flutter πŸš€
Favicon
custom lint rules in flutter
Favicon
How to Clear Cookies in Flutter Custom Tabs?
Favicon
Flutter

Featured ones: