ViewModel — কী, Android Jetpack-এ UI ডেটা ব্যবস্থাপনা

লেখক: IT Sectr প্রকাশিত: 2026-02-19 পড়ার সময়: 9 মিনিট

ViewModel হল একটি Android Jetpack Architecture উপাদান যা Activity এবং Fragment-এর জীবনচক্র বিবেচনায় রেখে UI ডেটা সংরক্ষণ এবং পরিচালনার জন্য ডিজাইন করা হয়েছে। Google I/O 2025-এর মতে, Jetpack-এর উপর নির্মিত 82% আধুনিক Android অ্যাপ্লিকেশনে ViewModel ব্যবহৃত হয়। সাধারণ ক্লাসের বিপরীতে, ViewModel স্বয়ংক্রিয়ভাবে স্ক্রিন রোটেশন এবং অন্যান্য কনফিগারেশন পরিবর্তন থেকে রক্ষা পায়, ডেটা হারানো ছাড়াই UI অবস্থা বজায় রাখে। MVVM (Model-View-ViewModel) আর্কিটেকচার ViewModel-এর উপর একটি কেন্দ্রীয় স্তর হিসাবে নির্ভর করে যা ব্যবসায়িক লজিককে ইন্টারফেসের সাথে সংযুক্ত করে।

মূল বিষয়

  • ViewModel — UI ডেটা সংরক্ষণের জন্য Jetpack উপাদান, স্ক্রিন রোটেশন এবং Activity পুনর্নির্মাণের প্রতিরোধী।
  • ViewModel-এর জীবনচক্র স্কোপের (Activity/Fragment/Composable) সাথে আবদ্ধ, পৃথক Activity ইনস্ট্যান্সের সাথে নয়।
  • viewModelScope — ViewModel-এর ভিতরে নির্মিত করুটিন, ViewModel পরিষ্কার করার সময় স্বয়ংক্রিয়ভাবে বাতিল হয়।
  • ViewModelProvider — Hilt বা Koin-এর মাধ্যমে ডিপেন্ডেন্সি ইনজেকশন সমর্থন সহ ViewModel তৈরির কারখানা।
  • MVVM-এ, ViewModel MVP-তে প্রেজেন্টারকে প্রতিস্থাপন করে, LiveData বা StateFlow-এর মাধ্যমে নির্দিষ্ট View-এর সাথে বাঁধাই দূর করে।

Android-এ ViewModel কী?

ViewModel হল Android Jetpack লাইব্রেরির একটি ক্লাস যা ব্যবহারকারী ইন্টারফেস সম্পর্কিত ডেটা সংরক্ষণ এবং পরিচালনার জন্য ডিজাইন করা হয়েছে, Activity বা Fragment-এর জীবনচক্র বিবেচনায় রেখে। ViewModel-এর প্রধান কাজ হল ডেটা প্রস্তুতির লজিককে UI স্তর থেকে পৃথক করা এবং কনফিগারেশন পরিবর্তনের সময় যেমন স্ক্রিন রোটেশন, থিম পরিবর্তন বা লোকেল পরিবর্তনের সময় এই ডেটা সংরক্ষণ করা।

ViewModel আসার আগে, ডেভেলপাররা UI অবস্থা সরাসরি Activity বা Fragment-এ সংরক্ষণ করতেন। স্ক্রিন ঘুরালে, Android Activity ধ্বংস করে এবং একটি নতুন তৈরি করে — সমস্ত অসংরক্ষিত ডেটা হারিয়ে যেত। সমাধান ছিল onSaveInstanceState()-এর মাধ্যমে অবস্থা সংরক্ষণ বা onRetainNonConfigurationInstance() ব্যবহার করা, কিন্তু উভয় পদ্ধতিতে ম্যানুয়াল ব্যবস্থাপনা এবং সিরিয়ালাইজেশন প্রয়োজন ছিল এবং জটিল অবজেক্টের জন্য উপযুক্ত ছিল না। ViewModel এই সমস্যাটি ফ্রেমওয়ার্ক স্তরে সমাধান করে: ডেটা UI থেকে আলাদাভাবে মেমরিতে থাকে এবং Activity পুনর্নির্মাণের সময় স্বয়ংক্রিয়ভাবে ফিরে আসে।

Android Developers ডকুমেন্টেশন (2025) অনুসারে, ViewModel প্রক্রিয়ার RAM-এ ডেটা সংরক্ষণ করে — এটি onSaveInstanceState()-এর মাধ্যমে Bundle থেকে পুনরুদ্ধারের চেয়ে 10–50 গুণ দ্রুত, যেখানে বাইট অ্যারেতে সিরিয়ালাইজেশন প্রয়োজন। ViewModel সেই সমস্ত স্ক্রিনের জন্য সুপারিশ করা হয় যেখানে ডেটা সরল প্রিমিটিভ বা স্ট্রিং-এর চেয়ে জটিল।

ViewModel জীবনচক্র: Activity থেকে কীভাবে আলাদা

ViewModel জীবনচক্র মৌলিকভাবে Activity জীবনচক্র থেকে আলাদা: ViewModel স্ক্রিন রোটেশনে ধ্বংস হয় না এবং স্কোপ সম্পূর্ণরূপে শেষ না হওয়া পর্যন্ত বেঁচে থাকে (Activity.finish() বা Fragment সরানো হয়েছে)। এর অর্থ হল ViewModel-এ লোড করা যেকোনো ডেটা নেটওয়ার্ক বা ডেটাবেস থেকে পুনরায় লোড না করেই কনফিগারেশন পরিবর্তনের সময় উপলব্ধ থাকে।

Activity তৈরির সময়, সিস্টেম ViewModelProvider-এর মাধ্যমে ViewModel বরাদ্দ করে। ViewModelProvider.get(ViewModel::class.java)-এর প্রথম কলেই একটি নতুন ViewModel ইনস্ট্যান্স তৈরি হয়। পরবর্তী কলগুলিতে (রোটেশনের পরেও) একই ইনস্ট্যান্স ফিরে আসে। ViewModel পরিষ্কার করা স্বয়ংক্রিয়ভাবে onCleared() কল করার সময় ঘটে — এই পদ্ধতিটি তখনই কল হয় যখন Activity শেষ (finish()) হয় বা Fragment সম্পূর্ণরূপে সরানো হয়। ডেভেলপার onCleared() ওভাররাইড করতে পারেন সম্পদ মুক্ত করার জন্য: Flow থেকে আনসাবস্ক্রাইব করা, করুটিন বাতিল করা, সকেট বন্ধ করা।

Google Jetpack ডকুমেন্টেশনে জোর দেয়: ViewModel-এর ভিতরে কখনও Activity বা View-এর রেফারেন্স সংরক্ষণ করবেন না — এটি মেমরি লিকের কারণ কারণ ViewModel তার UI সহ Activity-কে超越 করে বেঁচে থাকে। পরিবর্তে, ViewModel এবং UI-এর মধ্যে ডেটা স্থানান্তরের জন্য LiveData, StateFlow বা SavedStateHandle ব্যবহার করুন।

MVVM আর্কিটেকচারে ViewModel

MVVM (Model-View-ViewModel) প্যাটার্নে, ViewModel View (Activity/Fragment) এবং Model (রিপোজিটরি, DB, API)-এর মধ্যে একটি কেন্দ্রীয় স্থান দখল করে। View ViewModel (LiveData, StateFlow)-এর রিয়েক্টিভ ডেটায় সাবস্ক্রাইব করে এবং সেগুলি পরিবর্তন হলে স্বয়ংক্রিয়ভাবে আপডেট হয়। ViewModel View-এর অস্তিত্ব সম্পর্কে জানে না — এটি কেবল ডেটা এবং কমান্ড সরবরাহ করে, এবং View সিদ্ধান্ত নেয় কীভাবে সেগুলি প্রদর্শন করতে হবে।

MVP এবং MVVM-এর তুলনা: MVP-তে, প্রেজেন্টার সরাসরি View (ইন্টারফেস) পদ্ধতি কল করে, শক্ত সংযোগ তৈরি করে। MVVM-এ, ViewModel রিয়েক্টিভ ডেটা স্ট্রিম প্রকাশ করে এবং View সেগুলিতে সাবস্ক্রাইব করে — সংযোগটি একমুখী এবং পরীক্ষাযোগ্য। JetBrains Developer Survey (2024) অনুসারে, 68% Android ডেভেলপার MVVM-কে তাদের প্রাথমিক আর্কিটেকচার হিসাবে ব্যবহার করেন, এবং ViewModel এই প্যাটার্নের একটি মূল উপাদান।

IT Sectr-এ, আমরা 2018 সাল থেকে সমস্ত বাণিজ্যিক Kotlin প্রকল্পে ViewModel-সহ MVVM ব্যবহার করছি। অনুশীলন দেখায় যে এই পদ্ধতি দায়িত্বের স্পষ্ট বিভাজন এবং এমুলেটর ছাড়াই ব্যবসায়িক লজিকের পরীক্ষণযোগ্যতার কারণে UI লজিক ডিবাগিং সময় 30–40% কমিয়ে দেয়।

ViewModelProvider এবং কারখানা: প্যারামিটার সহ তৈরি

ViewModelProvider Fragment বা Activity-তে ViewModel পাওয়ার মানক উপায়। ডিফল্টরূপে, ViewModelProvider খালি কন্সট্রাক্টরের (কোনো আর্গুমেন্ট ছাড়া) মাধ্যমে ViewModel তৈরি করে। যদি ViewModel-এর প্যারামিটার প্রয়োজন হয় (যেমন রিপোজিটরি বা অ্যাপ্লিকেশন কনটেক্সট), তাহলে ViewModelProvider.Factory প্রয়োগ করা প্রয়োজন।

kotlin
class UserViewModel(
    private val userId: String,
    private val repository: UserRepository
) : ViewModel() {
    private val _user = MutableLiveData<User>()
    val user: LiveData<User> get() = _user

    fun loadUser() {
        viewModelScope.launch {
            _user.value = repository.getUser(userId)
        }
    }
}

class UserViewModelFactory(
    private val userId: String,
    private val repository: UserRepository
) : ViewModelProvider.Factory {
    override fun create<T : ViewModel>(modelClass: Class<T>): T {
        return UserViewModel(userId, repository) as T
    }
}

Fragment বা Activity থেকে ViewModel পাওয়ার সময় কারখানাটি ViewModelProvider-এ দেওয়া হয়। SavedStateHandle হল AndroidX 1.2.0-তে প্রবর্তিত একটি বিকল্প প্যারামিটার পাসিং প্রক্রিয়া: ViewModel স্বয়ংক্রিয়ভাবে কন্সট্রাক্টরের মাধ্যমে SavedStateHandle গ্রহণ করে এবং কাস্টম কারখানা না লিখেই Bundle-এর মাধ্যমে আর্গুমেন্ট পাস করা হয়।

ViewModel-এ viewModelScope এবং করুটিন

viewModelScope হল ViewModel-এ নির্মিত এবং তার জীবনচক্রের সাথে আবদ্ধ CoroutineScope। viewModelScope-তে লঞ্চ করা সমস্ত করুটিন onCleared() কল করার সময় স্বয়ংক্রিয়ভাবে বাতিল হয়ে যায়, যা ViewModel ধ্বংসের পরে মেমরি লিক এবং ব্যাকগ্রাউন্ড অপারেশন প্রতিরোধ করে।

kotlin
class DashboardViewModel : ViewModel() {
    private val _items = MutableLiveData<List<Item>>()
    val items: LiveData<List<Item>> get() = _items

    fun loadDashboard() {
        viewModelScope.launch(Dispatchers.IO) {
            val result = repository.fetchDashboard()
            withContext(Dispatchers.Main) {
                _items.value = result
            }
        }
    }

    override fun onCleared() {
        super.onCleared()
        // সমস্ত viewModelScope করুটিন স্বয়ংক্রিয়ভাবে বাতিল হয়ে যায়
    }
}

viewModelScope-তে করুটিন ডিফল্টরূপে Dispatchers.Main-এ চলে। নেটওয়ার্ক বা ডিস্ক অপারেশনের জন্য, withContext ব্যবহার করে Dispatchers.IO-তে স্যুইচ করুন বা launch-এ ডিসপ্যাচার নির্দিষ্ট করুন। Google (Android Dev Summit 2024) অনুসারে, ম্যানুয়াল Job ব্যবস্থাপনার তুলনায় viewModelScope ব্যবহার করুটিন-সম্পর্কিত মেমরি লিক 95% কমিয়ে দেয়।

Hilt এবং Koin-এর সাথে ViewModel: DI পদ্ধতি

Hilt হল Dagger-এর উপর নির্মিত Android-এর জন্য Google-এর অফিসিয়াল ডিপেন্ডেন্সি ইনজেকশন লাইব্রেরি। Hilt-এর সাথে, ViewModelProvider.Factory ম্যানুয়ালি লেখার প্রয়োজন নেই — শুধু ViewModel কন্সট্রাক্টরকে @HiltViewModel অ্যানোটেশন দিয়ে চিহ্নিত করুন। Hilt স্বয়ংক্রিয়ভাবে কারখানা তৈরি করে এবং কন্সট্রাক্টরে ঘোষিত ডিপেন্ডেন্সি ইনজেক্ট করে।

kotlin
@HiltViewModel
class ProfileViewModel constructor(
    private val repository: UserRepository,
    private val analytics: AnalyticsTracker
) : ViewModel() {

    private val _profile = MutableStateFlow<ProfileState>(ProfileState.Loading)
    val profile: StateFlow<ProfileState> get() = _profile

    fun loadProfile(userId: String) {
        viewModelScope.launch {
            _profile.value = ProfileState.Success(repository.getUser(userId))
            analytics.logEvent("profile_loaded")
        }
    }
}

// Fragment-এ — কারখানা ছাড়া:
val viewModel: ProfileViewModel = by viewModels()

Koin কোড জেনারেশন ছাড়া একটি বিকল্প DI লাইব্রেরি। Koin-এ, ViewModel viewModel { }-এর মাধ্যমে মডিউলে ঘোষণা করা হয় এবং Fragment-এ by viewModel()-এর মাধ্যমে পাওয়া যায়। Hilt এবং Koin-এর মধ্যে পছন্দ প্রকল্পের উপর নির্ভর করে: Hilt কম্পাইল সময়ে ডিপেন্ডেন্সি গ্রাফ যাচাইকরণ প্রদান করে, Koin হালকা এবং kapt/ksp প্রয়োজন হয় না। IT Sectr-এ, আমরা বড় প্রকল্পে (50+ স্ক্রিন) Hilt এবং মাঝারি প্রকল্পে Koin ব্যবহার করি।

কোড উদাহরণ: Kotlin-এ ViewModel

উদাহরণ 1: কাউন্টার সহ বেসিক ViewModel

একটি সরল ViewModel যা একটি পূর্ণসংখ্যা কাউন্টার সংরক্ষণ করে যা স্ক্রিন রোটেশনে রিসেট হয় না। MutableLiveData এবং LiveData ব্যবহারের মৌলিক প্যাটার্ন প্রদর্শন করে।

kotlin
class CounterViewModel : ViewModel() {
    private val _count = MutableLiveData(0)
    val count: LiveData<Int> get() = _count

    fun increment() {
        _count.value = (_count.value ?: 0) + 1
    }

    fun reset() {
        _count.value = 0
    }
}

উদাহরণ 2: SavedStateHandle সহ ViewModel

ViewModel যা সিস্টেম দ্বারা প্রক্রিয়া শেষ হলেও স্বয়ংক্রিয়ভাবে অবস্থা সংরক্ষণের জন্য SavedStateHandle ব্যবহার করে। SavedStateHandle হল একমাত্র প্রক্রিয়া যা অ্যাপকে ব্যাকগ্রাউন্ডে মিনিমাইজ এবং terminate করার সময় ডেটা সেভ করে।

kotlin
class FormViewModel(
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    val userName = savedStateHandle.getLiveData<String>("userName", "")
    val email = savedStateHandle.getLiveData<String>("email", "")

    fun saveName(name: String) {
        savedStateHandle["userName"] = name
    }

    fun saveEmail(email: String) {
        savedStateHandle["email"] = email
    }
}

SavedStateHandle থেকে LiveData স্বয়ংক্রিয়ভাবে শেষ মান Bundle-এ সংরক্ষণ করে। প্রক্রিয়া পুনর্নির্মাণের সময় (যেমন, অ্যাপ মিনিমাইজ এবং বন্ধ করার পরে), Bundle পুনরুদ্ধার হয় এবং LiveData পূর্ববর্তী মান গ্রহণ করে। Google পরীক্ষা অনুসারে, SavedStateHandle Bundle-এ 5 KB পর্যন্ত ডেটা সংরক্ষণের নিশ্চয়তা দেয় — টেক্সট ফিল্ড, ID এবং সিরিয়ালাইজড JSON অবজেক্টের জন্য যথেষ্ট।

প্রায়শই জিজ্ঞাসিত প্রশ্ন

ViewModel কীভাবে onSaveInstanceState থেকে আলাদা?

ViewModel প্রক্রিয়ার RAM-এ ডেটা সংরক্ষণ করে — এটি সিরিয়ালাইজেশন ছাড়াই তাত্ক্ষণিকভাবে উপলব্ধ, জটিল অবজেক্টের (তালিকা, Bitmap, নেটওয়ার্ক প্রতিক্রিয়া) জন্য উপযুক্ত। onSaveInstanceState() ডেটা Bundle-এ সিরিয়ালাইজ করে (Android 12 থেকে প্রতি লেনদেন সর্বোচ্চ 1 MB) এবং শুধুমাত্র সরল প্রিমিটিভ, String এবং Serializable/Parcelable-এর জন্য উপযুক্ত। ViewModel + SavedStateHandle হল Google-প্রস্তাবিত সংমিশ্রণ: রানটাইম ডেটার জন্য ViewModel, প্রক্রিয়া terminate হলে পুনরুদ্ধারের জন্য SavedStateHandle।

আমার কি ম্যানুয়ালি ViewModel পরিষ্কার করতে হবে?

না, সিস্টেম স্বয়ংক্রিয়ভাবে স্কোপ শেষ হলে onCleared() কল করে। viewModelStore.clear()-এর মাধ্যমে ম্যানুয়াল পরিষ্কার শুধুমাত্র পরীক্ষার ক্ষেত্রে পরীক্ষার কেসগুলির মধ্যে লিক প্রতিরোধের জন্য প্রয়োজন। প্রোডাকশন কোডে, কখনও ম্যানুয়ালি clear() কল করবেন না — এটি ViewModel জীবনচক্র ভঙ্গ করে এবং অপ্রত্যাশিত UI আচরণের কারণ হতে পারে।

Compose-এ ViewModel ব্যবহার করা যাবে কি?

হ্যাঁ, ViewModel Jetpack Compose-এ viewModel() ফাংশনের মাধ্যমে সম্পূর্ণ সমর্থিত। Compose-এ, ViewModel Composable স্কোপ স্তরে পাওয়া যায় এবং স্কোপ থেকে বের হলে স্বয়ংক্রিয়ভাবে পরিষ্কার হয়। MVVM-এর Compose সংস্করণকে Unidirectional Data Flow (UDF) বলা হয়: ViewModel StateFlow প্রকাশ করে এবং Composable ফাংশন collectAsState()-এর মাধ্যমে সাবস্ক্রাইব করে। রিডিউসার পদ্ধতির Compose রূপ হল ViewModel-সহ MVI।

ViewModel-এ কী সংরক্ষণ করা উচিত নয়?

Activity, Fragment, View, Context (Application ব্যতীত) এর রেফারেন্স সংরক্ষণ করা নিষিদ্ধ। এটি মেমরি লিকের কারণ কারণ ViewModel UI কনটেক্সটকে超越 করে বেঁচে থাকে। সিরিয়ালাইজড View অবস্থা (যেমন RecyclerView অবস্থান) সংরক্ষণ করবেন না — LayoutManager.onSaveInstanceState() ব্যবহার করুন। বড় পরিমাণ ডেটা (10 MB-এর বেশি) সংরক্ষণ এড়িয়ে চলুন — প্রক্রিয়া মিনিমাইজ করলে SavedStateHandle ছাড়া ডেটা হারিয়ে যাবে।

ViewModel কীভাবে পরীক্ষা করবেন?

ViewModel এমুলেটর ছাড়া সাধারণ Kotlin ক্লাসের মতো পরীক্ষা করা হয়: ইনস্ট্যান্স তৈরি করুন, পদ্ধতি কল করুন, LiveData বা StateFlow-এর অবস্থা পরীক্ষা করুন। করুটিন পরীক্ষার জন্য, TestDispatcher-সহ kotlinx-coroutines-test থেকে runTest ব্যবহার করুন। Hilt-সহ ViewModel-এর জন্য, পরীক্ষা Fragment-এ @HiltViewModelTest এবং hiltViewModel() ব্যবহার করুন। Google-এর মতে, ইউনিট পরীক্ষাগুলি ইন্সট্রুমেন্টেড পরীক্ষা ছাড়াই ViewModel লজিকের 80–90% কভার করে।

সারসংক্ষেপ

  • ViewModel — UI ডেটা সংরক্ষণের জন্য Jetpack উপাদান, অবস্থা না হারিয়ে কনফিগারেশন পরিবর্তন থেকে বেঁচে থাকে।
  • ViewModel জীবনচক্র স্কোপের (Activity/Fragment) সাথে আবদ্ধ, Activity ইনস্ট্যান্সের সাথে নয় — স্কোপ শেষ হলে পরিষ্কার হয়।
  • ViewModelProvider — ViewModel তৈরির জন্য কারখানা পদ্ধতি; প্যারামিটারের জন্য ViewModelProvider.Factory প্রয়োগ করুন।
  • viewModelScope — একটি নির্মিত CoroutineScope যা onCleared()-এ করুটিন স্বয়ংক্রিয়ভাবে বাতিল করে, মেমরি লিক দূর করে।
  • SavedStateHandle — প্রক্রিয়া terminate হলে অবস্থা সংরক্ষণের প্রক্রিয়া, ViewModel কন্সট্রাক্টরে একীভূত।
  • Hilt এবং @HiltViewModel — বড় প্রকল্পে ViewModel-এর জন্য DI-এর মানক উপায়; Koin — কোড জেনারেশন ছাড়া হালকা বিকল্প।
  • ViewModel হল MVVM এবং UDF আর্কিটেকচারের ভিত্তি, Google I/O 2025 অনুসারে 82% Jetpack অ্যাপে ব্যবহৃত।

আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব

IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।

প্রকল্প নিয়ে আলোচনা করুন

আরও পড়ুন