معماری 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 وجود ندارد.
روشهای پیاده سازی MVVM در پروژه های Android
دو روش برای پیادهسازی الگوی طراحی MVVM در پروژههای اندروید وجود دارد:
- استفاده از کتابخانه DataBinding منتشر شده توسط گوگل
- استفاده از هر ابزاری مانند 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 نخواهد داشت .
مرحله ۱: ایجاد یک پروژه جدید
- روی File کلیک کنید، سپس New > New Project.
- Empty activity را انتخاب کنید.
- زبان را به عنوان Java/Kotlin انتخاب کنید.
- حداقل 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 مناسب آمده است.
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;
}
}
package org.geeksforgeeks.demo
data class Model (
var email: String?,
var password: String?
)
مرحله ۴: ایجاد کلاس ViewModel
این کلاس شامل تمام متدهایی است که برای فراخوانی در طرحبندی برنامه مورد نیاز هستند. کلاس ViewModel از BaseObservable ارثبری میکند زیرا دادهها را به جریانها تبدیل میکند و هنگام تغییر ویژگی پیام toast، به View اطلاع میدهد.
کلاس ViewModel:
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() > ۵;
}
}
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 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>
طراحی رابط کاربری:

دوره متخصص فلاتر (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 بهترین راه برای تضمین پایداری و مدیریت آسان کدهاست.











































































































































































































































































































































































































