الگوی معماری mvvm در اندروید

الگوی معماری mvvm در اندروید

معماری MVVM در اندروید یکی از محبوب‌ترین الگوهای طراحی نرم‌افزار است که گوگل هم آن را پیشنهاد می‌کند. این معماری با جداسازی لایه‌ها (Model، View و ViewModel) باعث می‌شود کدها مرتب‌تر، قابل تست‌تر و توسعه پروژه‌ها ساده‌تر شود. اگر به دنبال ساخت اپلیکیشن‌های پایدار، مقیاس‌پذیر و حرفه‌ای هستید، شناخت و استفاده از MVVM یک ضرورت است. در این مطلب از سایت آموزش برنامه نویسی الکامکو شما را این معماری همراه با مثال آشنا می کنیم. با ما همراه باشید.

توسعه‌دهندگان همیشه کدهای تمیز و ساختاریافته را برای پروژه‌ها ترجیح می‌دهند. سازماندهی کدها بر اساس یک الگوی طراحی به نگهداری نرم‌افزار کمک می‌کند. با داشتن دانش در مورد تمام بخش‌های منطقی حیاتی برنامه اندروید ، اضافه کردن و حذف ویژگی‌های برنامه آسان‌تر می‌شود. علاوه بر این، الگوهای طراحی همچنین تضمین می‌کنند که تمام کدها بدون دخالت کلاس‌های دیگر، در تست واحد پوشش داده می‌شوند.

MVVM مخفف Model  View ViewModel الگوی معماری نرم‌افزار شناخته‌شده در صنعت است که بر تمام معایب الگوهای طراحی MVP و MVC غلبه می‌کند . MVVM پیشنهاد می‌کند که منطق ارائه داده‌ها (نماها یا رابط کاربری) از بخش منطق تجاری اصلی برنامه جدا شود.

لایه‌های MVVM

  • Model: این لایه مسئول انتزاع منابع داده است. مدل و ویومدل برای دریافت و ذخیره داده‌ها با هم کار می‌کنند.
  • View: هدف این لایه، آگاه کردن ViewModel از عملکرد کاربر است. این لایه ViewModel را مشاهده می‌کند و هیچ نوع منطق برنامه‌ای را شامل نمی‌شود.
  • ViewModel: جریان‌های داده‌ای را که مربوط به View هستند، نمایش می‌دهد. علاوه بر این، به عنوان پیوندی بین Model و View عمل می‌کند.

الگوی MVVM شباهت‌هایی با الگوی طراحی MVP (Model  View ViewMode) دارد، زیرا نقش ارائه‌دهنده توسط ViewModel ایفا می‌شود. با این حال، معایب الگوی MVP توسط MVVM به روش‌های زیر حل شده است:

  • ViewModel هیچ نوع ارجاعی به View نگه نمی‌دارد.
  • روابط to-1 زیادی بین View و ViewModel وجود دارد.
  • هیچ متد فعال‌سازی برای به‌روزرسانی View وجود ندارد.

دوره آموزش کاتلین پروژه محور | آموزش Kotlin از صفر تا صد

روش‌های پیاده‌ سازی MVVM در پروژه های Android

دو روش برای پیاده‌سازی الگوی طراحی MVVM در پروژه‌های اندروید وجود دارد:

  1. استفاده از کتابخانه DataBinding منتشر شده توسط گوگل
  2. استفاده از هر ابزاری مانند RxJava برای DataBinding.

۱- اتصال داده (Data Binding):

گوگل کتابخانه اتصال داده (Data Binding Library) را برای اندروید منتشر می‌کند که به توسعه‌دهندگان اجازه می‌دهد اجزای رابط کاربری را در طرح‌بندی‌های XML با مخازن داده برنامه متصل کنند. این امر به حداقل رساندن کد منطق اصلی برنامه که با View متصل می‌شود، کمک می‌کند. علاوه بر این، اتصال داده دو طرفه (Two-way Data Binding) برای اتصال اشیاء به طرح‌بندی‌های XML انجام می‌شود تا شیء و طرح‌بندی هر دو بتوانند داده‌ها را به یکدیگر ارسال کنند. این نکته را می‌توان با مثال این آموزش تجسم کرد.

Syntax for the two way data binding is @={variable}

پیاده‌سازی گام به گام 

در اینجا مثالی از یک برنامه اندروید با قابلیت ورود کاربر (User-Login) برای نمایش پیاده‌سازی الگوی معماری MVVM در پروژه‌ها آورده شده است. برنامه از کاربر می‌خواهد که شناسه ایمیل و رمز عبور را وارد کند. بر اساس ورودی‌های دریافتی، ViewModel به View اطلاع می‌دهد که چه چیزی را به عنوان یک پیام Toast نمایش دهد . ViewModel هیچ ارجاعی به View نخواهد داشت .

مرحله ۱: ایجاد یک پروژه جدید

  1. روی File کلیک کنید، سپس New > New Project.
  2. Empty activity را انتخاب کنید.
  3. زبان را به عنوان Java/Kotlin انتخاب کنید.
  4. حداقل SDK را بر اساس نیاز خود انتخاب کنید.

مرحله ۲: فعال کردن اتصال داده در فایل build.gradle.kts (سطح ماژول)

برای فعال کردن اتصال داده (Data Binding) در برنامه اندروید، کدهای زیر باید به فایل build.gradle.kts (ماژول:app) برنامه اضافه شوند :

فعال کردن اتصال داده (DataBinding):

Groovy

android {
   // add this
    buildFeatures {
        dataBinding = true
    }
}

افزونه‌ها را اضافه کنید:

Groovy

plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.kotlin.android)
    alias(libs.plugins.google.gms.google.services)
    id("kotlin-kapt") // add this
}

مرحله ۳: ایجاد کلاس Model

یک کلاس جدید به نام Model ایجاد کنید که شناسه ایمیل و رمز عبور وارد شده توسط کاربر را در خود نگه دارد. در زیر کد لازم برای پیاده‌سازی کلاس Model مناسب آمده است.

Model.java
package org.geeksforgeeks.demo;

public class Model {

    private String email;
    private String password;

    public Model(String email, String password) {
        this.email = email;
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
Model.kt
package org.geeksforgeeks.demo

data class Model (
    var email: String?,
    var password: String?
)

مرحله ۴: ایجاد کلاس ViewModel

این کلاس شامل تمام متدهایی است که برای فراخوانی در طرح‌بندی برنامه مورد نیاز هستند. کلاس ViewModel از BaseObservable ارث‌بری می‌کند زیرا داده‌ها را به جریان‌ها تبدیل می‌کند و هنگام تغییر ویژگی پیام toast، به View اطلاع می‌دهد.

کلاس ViewModel:

ViewModel.java
package org.geeksforgeeks.demo;

import android.util.Patterns;

import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;

public class ViewModel extends BaseObservable {

    // Creating an instance of the Model class
    private Model model = new Model("", "");

    // String variables for toast messages
    private final String successMessage = "Login successful";
    private final String errorMessage = "Email or Password is not valid";

    // String variable for toast message
    private String toastMessage;

    @Bindable
    public String getToastMessage() {
        return toastMessage;
    }

    private void setToastMessage(String toastMessage) {
        this.toastMessage = toastMessage;
        notifyPropertyChanged(BR.toastMessage);
    }

    // Getter and setter methods for email variable
    @Bindable
    public String getUserEmail() {
        return model.getEmail();
    }

    public void setUserEmail(String email) {
        model.setEmail(email);
        notifyPropertyChanged(BR.userEmail);
    }

    // Getter and setter methods for password variable
    @Bindable
    public String getUserPassword() {
        return model.getPassword();
    }

    public void setUserPassword(String password) {
        model.setPassword(password);
        notifyPropertyChanged(BR.userPassword);
    }

    // Actions to be performed when the user clicks the LOGIN button
    public void onButtonClicked() {
        setToastMessage(isValid() ? successMessage : errorMessage);
    }

    // Method to ensure fields are not empty and email/password validation
    private boolean isValid() {
        return !getUserEmail().isEmpty() && Patterns.EMAIL_ADDRESS.matcher(getUserEmail()).matches()
                && !getUserPassword().isEmpty() && getUserPassword().length() > ۵;
    }
}
ViewModel.kt
package org.geeksforgeeks.demo

import android.util.Patterns
import androidx.databinding.BaseObservable
import androidx.databinding.Bindable

class ViewModel : BaseObservable() {

    // Creating an instance of the Model class
    private var model: Model = Model("", "")

    // String variables for toast messages
    private val successMessage = "Login successful"
    private val errorMessage = "Email or Password is not valid"

    // String variable for toast message
    @get:Bindable
    var toastMessage: String? = null
        private set(value) {
            field = value
            notifyPropertyChanged(BR.toastMessage)
        }

    // Getter and setter methods for email variable
    @get:Bindable
    var userEmail: String?
        get() = model.email
        set(value) {
            model.email = value
            notifyPropertyChanged(BR.userEmail)
        }

    // Getter and setter methods for password variable
    @get:Bindable
    var userPassword: String?
        get() = model.password
        set(value) {
            model.password = value
            notifyPropertyChanged(BR.userPassword)
        }

    // Actions to be performed when the user clicks the LOGIN button
    fun onButtonClicked() {
        toastMessage = if (isValid()) successMessage else errorMessage
    }

    // Method to ensure fields are not empty and email/password validation
    private fun isValid(): Boolean {
        return !userEmail.isNullOrEmpty() && Patterns.EMAIL_ADDRESS.matcher(userEmail!!).matches()
                && !userPassword.isNullOrEmpty() && userPassword!!.length > ۵
    }
}

حله ۵: کار با فایل activity_main.xml

فایل activity_main.xml را باز کنید و دو EditText  برای دریافت ورودی‌های ایمیل و رمز عبور اضافه کنید. یک دکمه ورود نیز برای اعتبارسنجی ورودی کاربر و نمایش پیام Toast مناسب مورد نیاز است. در زیر کد لازم برای طراحی یک طرح‌بندی مناسب برای activity آمده است.

نکته: برای عملکرد صحیح کتابخانه اتصال داده، لازم است تگ layout در بالا تنظیم شود. تگ constraint layout مربوط به XML در این مورد کار نخواهد کرد.

activity_main.xml:

XML
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:bind="http://schemas.android.com/tools">

    <data>
        <variable
            name="viewModel"
            type="org.geeksforgeeks.demo.ViewModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:padding="16dp"
        android:orientation="vertical">

        <EditText
            android:id="@+id/inEmail"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:layout_marginBottom="20dp"
            android:hint="Enter your Email ID"
            android:inputType="textEmailAddress"
            android:padding="8dp"
            android:text="@={viewModel.userEmail}" />

        <EditText
            android:id="@+id/inPassword"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:hint="Enter your password"
            android:inputType="textPassword"
            android:padding="8dp"
            android:text="@={viewModel.userPassword}" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="32dp"
            android:onClick="@{()-> viewModel.onButtonClicked()}"
            android:text="Login"
            android:textSize="24sp"
            bind:toastMessage="@{viewModel.toastMessage}" />

    </LinearLayout>
</layout>

طراحی رابط کاربری:

طراحی رابط کاربری در معماری MVVM در اندروید

دوره متخصص فلاتر (Flutter) | دوره آموزش فلاتر پروژه محور از مبتدی تا پیشرفته

مرحله ۶: تعریف قابلیت‌های View در فایل MainActivity

کلاس View مسئول به‌روزرسانی رابط کاربری برنامه اندروید است. بر اساس تغییرات در پیام Toast ارائه شده توسط ViewModel، آداپتور اتصال (Binding Adapter) لایه View را فعال می‌کند. تنظیم‌کننده پیام Toast، ناظر (View) را از تغییرات داده‌ها مطلع می‌کند. پس از آن، View اقدامات مناسب را انجام می‌دهد.

MainActivity File:

MainActivity.java

package org.geeksforgeeks.demo;

import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.BindingAdapter;
import androidx.databinding.DataBindingUtil;

import org.geeksforgeeks.demo.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // ViewModel updates the Model after observing changes in the View
        // Model will also update the View via the ViewModel
        ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        // Assigning the ViewModel to the binding
        ViewModel viewModel = new ViewModel();
        activityMainBinding.setViewModel(viewModel);

        // Executes pending bindings immediately
        activityMainBinding.executePendingBindings();
    }

    // BindingAdapter to show the toast message
    @BindingAdapter("toastMessage")
    public static void runMe(View view, String message) {
        if (message != null && !message.isEmpty()) {
            Toast.makeText(view.getContext(), message, Toast.LENGTH_SHORT).show();
        }
    }
}

MainActivity.kt

package org.geeksforgeeks.demo

import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.BindingAdapter
import androidx.databinding.DataBindingUtil
import org.geeksforgeeks.demo.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // ViewModel updates the Model after observing changes in the View
        // Model will also update the View via the ViewModel
        val activityMainBinding: ActivityMainBinding =
            DataBindingUtil.setContentView(this, R.layout.activity_main)

        activityMainBinding.viewModel = ViewModel()
        activityMainBinding.executePendingBindings()
    }

    companion object {
        @JvmStatic
        @BindingAdapter("toastMessage")
        fun runMe(view: View, message: String?) {
            message?.let {
                Toast.makeText(view.context, it, Toast.LENGTH_SHORT).show()
            }
        }
    }
}

خروجی پروژه 

 

چرا باید از MVVM در اندروید استفاده کنیم؟

دلایل اصلی استفاده از معماری MVVM (Model-View-ViewModel) در اندروید به شرح زیر است:

۱. بهبود تست‌پذیری (Improved Testability)

MVVM با تفکیک منطق از رابط کاربری، هسته منطق برنامه را در ViewModel قرار می‌دهد. این امر اجرای تست‌های واحد (Unit Tests) را برای منطق کسب‌وکار، بدون نیاز به شبیه‌ساز یا دستگاه اندرویدی، بسیار آسان و سریع می‌کند.

۲. جداسازی دغدغه‌ها (Separation of Concerns)

این الگو وظایف را به طور شفاف تفکیک می‌کند:

  • View (Activity/Fragment): فقط مسئول UI و دریافت ورودی است.
  • ViewModel: مسئول آماده‌سازی داده‌ها برای نمایش و نگهداری منطق نمایش است.
  • Model/Repository: مسئول مدیریت داده‌ها و منطق کسب‌وکار است.

این تفکیک باعث می‌شود که کد تمیزتر، قابل نگهداری‌تر و توسعه‌پذیرتر باشد، زیرا تغییر در یک بخش بر بخش‌های دیگر تأثیر نمی‌گذارد.

۳. مدیریت چرخه حیات (Lifecycle Management)

کلاس ViewModel از Jetpack برای حل مشکل مدیریت داده‌ها در برابر تغییرات پیکربندی (مثل چرخش صفحه) طراحی شده است.

  • حفظ داده‌ها: ViewModel می‌تواند از تخریب و بازسازی Activity یا Fragment جان سالم به در ببرد و داده‌ها را حفظ کند، که از بارگذاری مجدد غیرضروری جلوگیری می‌کند.
  • ارتباط امن: استفاده از LiveData یا Flow تضمین می‌کند که View فقط زمانی که فعال است داده‌ها را دریافت کند، که به جلوگیری از نشت حافظه (Memory Leaks) کمک می‌کند.

۴. کاهش کدهای پشت سر هم (Less Code-Behind)

با استفاده از Data Binding، View مستقیماً به داده‌های ViewModel متصل می‌شود. این امر به‌روزرسانی‌های UI را خودکار کرده و نیاز به کدهای دستی در Activity یا Fragment (مانند findViewById و به‌روزرسانی مستقیم ویجت‌ها) را به حداقل می‌رساند و کد View را بسیار ساده‌تر می‌کند.

همچنین بخوانید: برنامه اندروید استودیو | آموزش نصب اندروید استودیو | دوره آموزشی اندروید استودیو

سوالات متداول پیرامون mvvm اندروید

  • ۱. mvvm اندروید چیست و چرا استفاده می‌شود؟

الگوی MVVM در کدنویسی اندروید یک معماری نرم‌افزاری است که سه بخش Model، View و ViewModel را از هم جدا می‌کند. این جداسازی باعث می‌شود کدها مرتب‌تر، تست‌پذیرتر و نگهداری پروژه ساده‌تر شود. در عمل، منطق برنامه در ViewModel و داده‌ها در Model نگهداری می‌شوند و View فقط نمایش می‌دهد، بنابراین وابستگی بین بخش‌ها کمتر می‌شود.

  • ۲. چه تفاوتی بین mvvm در اندروید و معماری‌های دیگر مثل MVC یا MVP وجود دارد؟

در MVC یا MVP معمولاً View و منطق تجاری بیش از حد به هم وابسته می‌شوند، اما در MVVM اندروید ارتباط View و ViewModel از طریق DataBinding یا LiveData برقرار می‌شود و ViewModel هیچ وابستگی مستقیمی به View ندارد. این موضوع باعث می‌شود کد تمیزتر و قابل تست‌تر باشد و توسعه‌دهندگان راحت‌تر تیمی کار کنند.

  • ۳. برای پیاده‌سازی mvvm در اندروید به چه ابزارهایی نیاز داریم؟

اصلی‌ترین ابزار برای پیاده‌سازی mvvm در اندروید استفاده از Android Architecture Components مثل LiveData و ViewModel است. همچنین DataBinding یا ViewBinding امکان اتصال مستقیم بین داده‌ها و UI را فراهم می‌کنند. اگر پروژه پیچیده‌تر باشد، می‌توان از RxJava یا Kotlin Coroutines هم برای مدیریت جریان داده‌ها استفاده کرد.

همچنین بخوانید: آموزش معماری MVP در اندروید با Rxjava

  • ۴. چه مزایایی استفاده از mvvm در اندروید دارد؟

مهم‌ترین مزیت mvvm در اندروید این است که تغییرات داده‌ها به‌صورت خودکار در UI بازتاب پیدا می‌کنند، کدها تمیزتر و قابل تست‌تر می‌شوند و توسعه‌دهندگان می‌توانند راحت‌تر بخش‌های مختلف پروژه را به‌طور مستقل مدیریت کنند. علاوه بر این، نگهداری و افزودن قابلیت‌های جدید در آینده ساده‌تر خواهد بود.

  • ۵. آیا mvvm در اندروید برای همه پروژه‌ها مناسب است؟

الگوی mvvm در برنامه نویسی اندروید برای پروژه‌های برنامه نویسی متوسط و بزرگ بسیار مناسب است، چون ساختارمند بودن آن جلوی شلوغی کد و مشکلات نگهداری را می‌گیرد. اما برای پروژه‌های کوچک و ساده ممکن است کمی پیچیدگی اضافی ایجاد کند و معماری ساده‌تری مثل MVP کافی باشد.

دوره متخصص اندروید | پکیج کامل آموزش برنامه نویسی اندروید

نتیجه گیری

استفاده از mvvm اندروید روشی مدرن و کارآمد برای ساخت اپلیکیشن‌ اندروید باکیفیت است. این معماری به توسعه‌دهندگان کمک می‌کند تا پروژه‌های خود را با ساختاری تمیز و انعطاف‌پذیر پیاده‌سازی کنند و در آینده به راحتی آن‌ها را گسترش دهند. اگرچه در پروژه‌های کوچک ممکن است ساده‌تر عمل شود، اما برای اپلیکیشن‌های متوسط و بزرگ، انتخاب MVVM بهترین راه برای تضمین پایداری و مدیریت آسان کدهاست.

دوره ساخت اپلیکیشن فروشگاهی اندروید با معماری MVVM و کاتلین

اشتراک گذاری این صفحه در شبکه های اجتماعی:

commentشما بگید!

شما چه سوالی درباره این موضوع دارید که اینجا مطرح نشده است؟ لطفا تجربیات خودتان را در این زمینه حتما توی کامنت برای ما بنویسید. منتظر نظرات، پیشنهادات و سوالات شما در همین صفحه از سایت آموزش برنامه نویسی الکامکو هستیم…

توجه

مقاله هایی که در سایت به صورت رایگان قرار گرفته است فقط برای مطالعه بیشتر شما کاربران عزیز می باشد. از هرگونه تماس تلفنی با پشتیبانی سایت و سوال در مورد محتوای مقاله ها خودداری شود.

shareاشتراک گذاری این مطلب

shareآخرین مقالات

توجه

مقاله هایی که در سایت به صورت رایگان قرار گرفته است فقط برای مطالعه بیشتر شما کاربران عزیز می باشد. از هرگونه تماس تلفنی با پشتیبانی سایت و سوال در مورد محتوای مقاله ها خودداری شود.

آخرین مقالات

آموزش های تکمیل شده

آموزش اندروید استودیو - آموزش android studio - آموزش برنامه نویسی اندروید الکامکو - ساخت اپلیکیشن اندروید - آموزش ساخت برنامه اندروید

آموزش ساخت برنامه اندروید پروژه محور، ساخت اپلیکیشن برای اندروید

دوره متخصص اندروید

دوره متخصص اندروید | پکیج کامل آموزش برنامه نویسی اندروید

آموزش ساخت اپلیکیشن فروشگاهی اندروید دیجی کالا Digikala - سورس دیجی کالا php - الکامکو

آموزش ساخت اپلیکیشن فروشگاهی اندروید دیجی کالا + سورس

آموزش برنامه نویسی اندروید با کاتلین - برنامه نویسی کاتلین - آموزش kotlin - آموزش زبان برنامه نویسی کاتلین

دوره آموزش کاتلین پروژه محور | آموزش Kotlin از صفر تا صد

آموزش طراحی رابط کاربری (طراحی UI اندروید) و آموزش طراحی تجربه کاربری (طراحی UX اندروید) - آموزش برنامه نویسی اندروید الکامکو

دوره جامع آموزش طراحی رابط کاربری (UI) و تجربه کاربری (UX) در اندروید

دوره آموزش ساخت اپلیکیشن اندروید فیلیمو - خرید اشتراک فیلیمو - خرید اشتراک فیلم - برنامه فیلیمو برای اندروید - ساخت اپلیکیشن فیلم و سریال - ساخت برنامه فیلیمو | مرجع آموزش برنامه نویسی اندروید الکامکو

آموزش ساخت اپلیکیشن اندروید فیلیمو همراه با سورس کد مشابه فیلیمو

توجه

مقاله هایی که در سایت به صورت رایگان قرار گرفته است فقط برای مطالعه بیشتر شما کاربران عزیز می باشد. از هرگونه تماس تلفنی با پشتیبانی سایت و سوال در مورد محتوای مقاله ها خودداری شود.

0 دیدگاه
بازخورد درون خطی
مشاهده همه نظرات