Debug School

rakesh kumar
rakesh kumar

Posted on

Explain MVVM (Model-View-ViewModel) in flutter

The MVVM (Model-View-ViewModel) architecture is a design pattern that separates the development of the graphical user interface (UI) from the development of the business logic or back-end logic. This separation of concerns makes it easier to manage, test, and maintain code.

In Flutter, the MVVM pattern can be implemented using various state management solutions, such as Provider, Riverpod, or GetX. Here, I'll explain the MVVM architecture and provide a complete example using the Provider package.

MVVM Components

Model: Represents the data and business logic. It is responsible for retrieving data from the server or database.
View: Represents the UI components and displays data to the user. It listens to changes in the ViewModel and updates the UI accordingly.
ViewModel: Acts as a bridge between the Model and the View. It holds the data, handles business logic, and provides methods for the View to interact with the data.
Example: MVVM in Flutter using Provider
Step 1: Add Dependencies
Add the provider package to your pubspec.yaml file:

dependencies:
  flutter:
    sdk: flutter
  provider: ^5.0.0
  http: ^0.14.0
Enter fullscreen mode Exit fullscreen mode

Run flutter pub get to install the packages.

Step 2: Create the Model
Define a model class to represent the data. For example, a User class:

class User {
  final String name;
  final String email;

  User({required this.name, required this.email});

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      name: json['name'],
      email: json['email'],
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Create the ViewModel
The ViewModel will manage the state and logic. It uses a ChangeNotifier to notify the View of any changes.

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'user.dart';

class UserViewModel extends ChangeNotifier {
  List<User> _users = [];
  bool _isLoading = false;

  List<User> get users => _users;
  bool get isLoading => _isLoading;

  Future<void> fetchUsers() async {
    _isLoading = true;
    notifyListeners();

    final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/users'));

    if (response.statusCode == 200) {
      List<dynamic> data = json.decode(response.body);
      _users = data.map((json) => User.fromJson(json)).toList();
    }

    _isLoading = false;
    notifyListeners();
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Create the View
The View will listen to the ViewModel and update the UI accordingly.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'user_view_model.dart';
import 'user.dart';

class UserListView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('User List')),
      body: Consumer<UserViewModel>(
        builder: (context, viewModel, child) {
          if (viewModel.isLoading) {
            return Center(child: CircularProgressIndicator());
          }

          return ListView.builder(
            itemCount: viewModel.users.length,
            itemBuilder: (context, index) {
              User user = viewModel.users[index];
              return ListTile(
                title: Text(user.name),
                subtitle: Text(user.email),
              );
            },
          );
        },
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Set Up the Main Entry Point
Initialize the ViewModel and set up the Provider.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'user_view_model.dart';
import 'user_list_view.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => UserViewModel()..fetchUsers(),
      child: MaterialApp(
        home: UserListView(),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Summary

Model: Represents the data structure (User class).
ViewModel: Manages the state and business logic (UserViewModel class).
View: Displays the UI and listens for changes in the ViewModel (UserListView class).

Benefits of MVVM

Separation of Concerns: Clear separation between UI and business logic.
Testability: Easier to test business logic without involving UI code.
Maintainability: Modular code that is easier to maintain and extend.
By following the MVVM pattern, you can build scalable and maintainable Flutter applications with a clear separation of concerns.

Top comments (0)