DEV Community

flfljh
flfljh

Posted on

HarmonyOS Flutter MVVM Architecture Pattern

HarmonyOS Next


Preface

Implementing the MVVM (Model-View-ViewModel) architecture in Flutter separates the UI (View) from business logic (Model and ViewModel), enhancing code maintainability and readability.


Overall Architecture Overview

Model

  • Role: Data layer responsible for business logic and data management.
  • Example: Manages a counter value and increment logic.

View

  • Role: User interface layer for displaying data and handling user input.
  • Example: Displays the counter value and a button to increment it.

ViewModel

  • Role: Acts as an intermediary between Model and View.

Responsibilities

:

  • Exposes data to the View.
  • Handles user input (e.g., button taps).
  • Notifies the View to update when data changes.

Detailed File Explanation

main.dart

import 'package:flutter/material.dart';
import 'package:mvvm/View/MyHomePage.dart';
import 'package:provider/provider.dart';
import 'Model/Model.dart';
import 'ViewModel/CounterViewModel.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter MVVM Example',
      home: ChangeNotifierProvider(
        create: (context) => CounterViewModel(CounterModel()),
        child: MyHomePage(),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Key Points:

  • Uses ChangeNotifierProvider to share CounterViewModel across the app.
  • MyHomePage accesses the ViewModel via Provider.of.

CounterViewModel.dart

import 'package:flutter/foundation.dart';
import '../Model/Model.dart';

class CounterViewModel extends ChangeNotifier {
  final CounterModel _counterModel;

  CounterViewModel(this._counterModel);

  int get counter => _counterModel.counter;

  void incrementCounter() {
    _counterModel.increment();
    notifyListeners();
  }
}
Enter fullscreen mode Exit fullscreen mode

Key Points:

  • Extends ChangeNotifier to enable reactive updates.
  • incrementCounter() updates the Model and triggers UI refresh.

MyHomePage.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../ViewModel/CounterViewModel.dart';

class MyHomePage extends StatefulWidget {
  MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    final counterViewModel = Provider.of<CounterViewModel>(context);

    return Scaffold(
      appBar: AppBar(title: Text('Flutter MVVM Example')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Flutter HarmonyOS MVVM Principle (Dart)'),
            Text('Page requests data from ViewModel'),
            Text('ViewModel requests data from Model'),
            Text('ViewModel notifies UI updates via notifyListeners'),
            Text(
              '${counterViewModel.counter}',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: counterViewModel.incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Key Points:

  • Uses Provider to access the ViewModel.
  • UI elements (e.g., Text, FloatingActionButton) bind to ViewModel properties.

Model.dart

class CounterModel {
  int _counter = 0;

  int get counter => _counter;

  void increment() {
    _counter++;
  }
}
Enter fullscreen mode Exit fullscreen mode

Key Points:

  • Encapsulates data (_counter) and business logic (increment()).

MVVM Architecture Analysis

Separation of Concerns

  • Model: Manages data (e.g., _counter) and business rules.
  • View: Focuses solely on UI rendering (e.g., Text, Button).
  • ViewModel: Bridges Model and View, handling data transformations and user interactions.

Data Binding

  • Implemented via ChangeNotifier and Provider.
  • When _counter changes in CounterModel, notifyListeners() triggers UI updates.

Maintainability & Testability

  • Maintainability: Each layer has a clear responsibility.

Testability

:

  • Model can be tested independently.
  • ViewModel can be unit-tested without UI dependencies.

Summary

The MVVM pattern in Flutter (using Provider) achieves:

  1. Decoupling: Separates UI logic from business logic.
  2. Reactivity: Automatic UI updates via data binding.
  3. Scalability: Simplifies complex app architectures.

By leveraging Flutter’s ecosystem, developers can build robust, maintainable apps with clean separation of concerns.

Top comments (0)