Bird
Raised Fist0
Android Kotlinmobile~15 mins

ViewModel creation in Android Kotlin - Deep Dive

Choose your learning style10 modes available
Overview - ViewModel creation
What is it?
A ViewModel is a special class in Android apps that holds and manages UI-related data. It keeps this data safe even when the screen rotates or the app changes state. Creating a ViewModel means making this class to store and handle data separately from the screen itself.
Why it matters
Without ViewModels, data would be lost every time the screen changes, like rotating the phone. This would make apps feel slow and frustrating because they would reload or lose what the user was doing. ViewModels solve this by keeping data alive and ready, making apps smooth and reliable.
Where it fits
Before learning ViewModel creation, you should understand basic Android app structure and Kotlin classes. After this, you can learn about LiveData and data binding to connect ViewModels to the user interface.
Mental Model
Core Idea
A ViewModel is like a trusted assistant that holds your screen’s data safely, even when the screen is rebuilt or changed.
Think of it like...
Imagine you are cooking in a kitchen and your recipe notes are on a clipboard. If the kitchen is cleaned and rearranged (like the screen rotating), your clipboard stays safe with all the notes intact, so you don’t lose your place. The ViewModel is that clipboard.
┌───────────────┐
│   Activity/   │
│   Fragment    │
└──────┬────────┘
       │ uses
       ▼
┌───────────────┐
│   ViewModel   │
│ (holds data)  │
└───────────────┘
       ▲
       │ survives
       │ configuration
       │ changes
       ▼
┌───────────────┐
│   UI rebuild  │
Build-Up - 6 Steps
1
FoundationWhat is a ViewModel in Android
🤔
Concept: Introduces the ViewModel as a class that stores UI data separately from UI controllers.
In Android, screens are usually Activities or Fragments. When these screens change, like rotating the device, they are destroyed and recreated. A ViewModel is a class designed to hold data that the UI needs, so this data is not lost during these changes.
Result
You understand that ViewModels keep data safe across screen changes.
Understanding that UI data can be separated from the screen itself helps prevent common bugs where data disappears unexpectedly.
2
FoundationBasic Kotlin ViewModel Class Setup
🤔
Concept: Shows how to create a simple ViewModel class in Kotlin.
To create a ViewModel, you make a class that extends ViewModel from Android's architecture library. For example: class MyViewModel : ViewModel() { var count = 0 } This class can hold variables and functions to manage UI data.
Result
You can write a basic ViewModel class that holds data.
Knowing how to define a ViewModel class is the first step to separating data from UI logic.
3
IntermediateConnecting ViewModel to UI Components
🤔Before reading on: Do you think you create a ViewModel instance with 'new' keyword or use a special method? Commit to your answer.
Concept: Explains how to get a ViewModel instance tied to the UI lifecycle using ViewModelProvider.
You don't create ViewModels with 'new'. Instead, you use ViewModelProvider to get the ViewModel linked to your Activity or Fragment: val viewModel = ViewModelProvider(this).get(MyViewModel::class.java) This ensures the ViewModel survives configuration changes and is shared properly.
Result
You can obtain a ViewModel instance that lives as long as the UI component.
Understanding the lifecycle-aware creation of ViewModels prevents memory leaks and data loss.
4
IntermediateStoring and Updating UI Data in ViewModel
🤔Before reading on: Do you think ViewModel variables update UI automatically or do you need extra steps? Commit to your answer.
Concept: Introduces how to store data in ViewModel and update it safely.
You can store simple variables in ViewModel, but to update UI automatically, you often use LiveData. For now, you can update variables like: viewModel.count += 1 But the UI won't know unless you observe changes.
Result
You can manage data inside ViewModel but need more to reflect changes on screen.
Knowing that ViewModel holds data but doesn't update UI by itself clarifies the need for observable data holders.
5
AdvancedUsing ViewModel with LiveData for Reactive UI
🤔Before reading on: Do you think LiveData is mandatory for ViewModel or optional? Commit to your answer.
Concept: Shows how LiveData inside ViewModel helps UI react to data changes automatically.
LiveData is a special data holder that notifies UI when data changes. Inside ViewModel: val count = MutableLiveData(0) To update: count.value = count.value?.plus(1) In UI, observe this LiveData to update views automatically.
Result
UI updates automatically when ViewModel data changes.
Understanding LiveData's role with ViewModel unlocks reactive and clean UI updates.
6
ExpertCustom ViewModel Factories for Parameterized Creation
🤔Before reading on: Can you create a ViewModel with constructor parameters directly via ViewModelProvider? Commit to your answer.
Concept: Explains how to create ViewModels that need parameters using a factory class.
ViewModelProvider by default calls a no-argument constructor. To pass parameters, create a factory: class MyViewModelFactory(private val repo: Repository) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { if (modelClass.isAssignableFrom(MyViewModel::class.java)) { return MyViewModel(repo) as T } throw IllegalArgumentException("Unknown ViewModel class") } } Then get ViewModel: val factory = MyViewModelFactory(repo) val viewModel = ViewModelProvider(this, factory).get(MyViewModel::class.java)
Result
You can create ViewModels with custom parameters safely.
Knowing how to use factories allows flexible and testable ViewModel creation in real apps.
Under the Hood
ViewModel objects are stored in a special container tied to the UI controller's lifecycle. When the UI controller (Activity/Fragment) is destroyed due to configuration changes, the ViewModel survives because the container keeps it alive. This container is cleared only when the UI controller is permanently finished. This mechanism prevents data loss and unnecessary reloads.
Why designed this way?
Android screens are recreated often, especially on rotation. Early apps lost data on these changes, frustrating users. ViewModel was designed to separate data from UI lifecycle, keeping data safe without complex manual saving. It balances memory use and data persistence by clearing ViewModels only when truly needed.
┌─────────────────────────────┐
│  Activity/Fragment lifecycle │
│  ┌───────────────────────┐  │
│  │ ViewModelStoreOwner   │  │
│  │ ┌───────────────────┐ │  │
│  │ │ ViewModelStore    │ │  │
│  │ │ ┌───────────────┐ │ │  │
│  │ │ │ ViewModel     │ │ │  │
│  │ │ └───────────────┘ │ │  │
│  │ └───────────────────┘ │  │
│  └───────────────────────┘  │
└─────────────────────────────┘
Myth Busters - 3 Common Misconceptions
Quick: Does creating a new ViewModel instance with 'MyViewModel()' work correctly for UI data persistence? Commit yes or no.
Common Belief:You can create a ViewModel by calling its constructor directly like any class.
Tap to reveal reality
Reality:ViewModels must be created via ViewModelProvider to be lifecycle-aware and survive configuration changes.
Why it matters:Creating ViewModel directly causes data loss on rotation and breaks lifecycle management, leading to bugs.
Quick: Does ViewModel automatically update the UI when its data changes? Commit yes or no.
Common Belief:ViewModel data changes automatically refresh the UI without extra code.
Tap to reveal reality
Reality:ViewModel holds data but does not notify UI; you need observable data like LiveData to update UI reactively.
Why it matters:Assuming automatic UI updates leads to stale UI and confusion about app behavior.
Quick: Is ViewModel designed to hold references to UI views like Buttons or TextViews? Commit yes or no.
Common Belief:It's okay to store UI elements inside ViewModel for easy access.
Tap to reveal reality
Reality:ViewModels should never hold references to UI views to avoid memory leaks and lifecycle issues.
Why it matters:Holding UI references causes memory leaks and crashes when UI is destroyed but ViewModel lives on.
Expert Zone
1
ViewModels are scoped to the lifecycle owner; sharing ViewModels between fragments requires using the activity as the owner.
2
ViewModelStore can hold multiple ViewModels; understanding this helps manage complex UI with multiple data holders.
3
Using SavedStateHandle inside ViewModel allows saving small amounts of UI state automatically across process death.
When NOT to use
Avoid using ViewModel for data that must persist beyond the app process lifecycle, such as user preferences or database storage. Use persistent storage solutions like Room or DataStore instead.
Production Patterns
In production, ViewModels are combined with LiveData or StateFlow for reactive UI, use dependency injection for factories, and integrate with repositories to separate data sources cleanly.
Connections
Observer Pattern
ViewModel often uses LiveData which implements the observer pattern to notify UI of data changes.
Understanding observer pattern clarifies how UI reacts to data changes without manual refresh calls.
Separation of Concerns (Software Design)
ViewModel separates UI data management from UI rendering logic, following separation of concerns principle.
Knowing this principle helps design cleaner, maintainable apps by dividing responsibilities.
Clipboard in Real Life
ViewModel acts like a clipboard holding important notes safe during kitchen cleaning (UI changes).
This cross-domain connection helps remember ViewModel’s role in preserving data safely.
Common Pitfalls
#1Creating ViewModel with constructor directly causes lifecycle issues.
Wrong approach:val viewModel = MyViewModel()
Correct approach:val viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
Root cause:Misunderstanding that ViewModel needs lifecycle-aware creation to survive configuration changes.
#2Storing UI views inside ViewModel causes memory leaks.
Wrong approach:class MyViewModel : ViewModel() { lateinit var button: Button }
Correct approach:class MyViewModel : ViewModel() { var count = 0 }
Root cause:Confusing ViewModel as a place to keep UI elements instead of data.
#3Expecting UI to update automatically without observable data.
Wrong approach:viewModel.count = 5 // UI does not update automatically
Correct approach:val count = MutableLiveData(0) count.value = 5 // UI observes and updates
Root cause:Not using LiveData or similar observable data holders with ViewModel.
Key Takeaways
ViewModel separates UI data from UI controllers to keep data safe during screen changes.
Always create ViewModels using ViewModelProvider to ensure lifecycle awareness and data persistence.
ViewModel alone does not update UI; use LiveData or other observable data holders for reactive updates.
Never store UI elements inside ViewModel to avoid memory leaks and lifecycle problems.
Advanced ViewModel creation uses factories to pass parameters, enabling flexible and testable designs.

Practice

(1/5)
1. What is the main purpose of a ViewModel in Android development?
easy
A. To define the layout of the app screen
B. To handle user input events directly
C. To store and manage UI-related data in a lifecycle conscious way
D. To manage network requests

Solution

  1. Step 1: Understand ViewModel role

    A ViewModel is designed to hold UI data safely during configuration changes like screen rotations.
  2. Step 2: Compare options

    Only To store and manage UI-related data in a lifecycle conscious way describes this purpose correctly; others describe unrelated tasks.
  3. Final Answer:

    To store and manage UI-related data in a lifecycle conscious way -> Option C
  4. Quick Check:

    ViewModel purpose = store UI data safely [OK]
Hint: ViewModel holds UI data safely during screen changes [OK]
Common Mistakes:
  • Confusing ViewModel with UI layout classes
  • Thinking ViewModel handles user input directly
  • Assuming ViewModel manages network calls
2. Which of the following is the correct way to declare a ViewModel class in Kotlin?
easy
A. class MyViewModel extends ViewModel {}
B. class MyViewModel : ViewModel() {}
C. fun MyViewModel() : ViewModel {}
D. val MyViewModel = ViewModel()

Solution

  1. Step 1: Recall Kotlin class syntax

    Kotlin uses a colon (:) to extend a class and parentheses for constructor calls.
  2. Step 2: Check each option

    class MyViewModel : ViewModel() {} uses correct Kotlin syntax for extending ViewModel; others use Java syntax or invalid declarations.
  3. Final Answer:

    class MyViewModel : ViewModel() {} -> Option B
  4. Quick Check:

    Kotlin inheritance uses ':' and parentheses [OK]
Hint: Use ':' to extend class in Kotlin, not 'extends' [OK]
Common Mistakes:
  • Using Java syntax 'extends' in Kotlin
  • Declaring ViewModel as a function
  • Assigning ViewModel to a val without class
3. Given this ViewModel code snippet, what will be the output when counter.value is printed after increment() is called twice?
class CounterViewModel : ViewModel() {
  val counter = MutableLiveData(0)
  fun increment() {
    counter.value = (counter.value ?: 0) + 1
  }
}
medium
A. 2
B. 1
C. null
D. 0

Solution

  1. Step 1: Understand initial value and increment

    counter starts at 0; each increment adds 1 to current value.
  2. Step 2: Calculate after two increments

    After first call: 0 + 1 = 1; after second call: 1 + 1 = 2.
  3. Final Answer:

    2 -> Option A
  4. Quick Check:

    Two increments from 0 = 2 [OK]
Hint: Each increment adds 1; two calls add 2 total [OK]
Common Mistakes:
  • Forgetting to unwrap nullable value
  • Assuming counter resets each time
  • Confusing LiveData with normal variable
4. Identify the error in this ViewModel code:
class SampleViewModel : ViewModel() {
  val data = MutableLiveData<String>()

  fun updateData(newData: String) {
    data.value = newData
  }

  fun getData(): String {
    return data.value
  }
}
medium
A. ViewModel class must be abstract
B. MutableLiveData cannot hold String values
C. updateData() should not modify LiveData value
D. getData() returns nullable String but declared as non-nullable

Solution

  1. Step 1: Check LiveData type and usage

    MutableLiveData<String> can hold String values; updateData() correctly sets value.
  2. Step 2: Analyze getData() return type

    data.value is nullable String?, but getData() returns non-nullable String, causing a type mismatch.
  3. Final Answer:

    getData() returns nullable String but declared as non-nullable -> Option D
  4. Quick Check:

    LiveData value is nullable; return type must match [OK]
Hint: LiveData.value is nullable; match return types carefully [OK]
Common Mistakes:
  • Ignoring nullable type of LiveData.value
  • Thinking ViewModel must be abstract
  • Believing LiveData can't hold String
5. You want to create a ViewModel that holds a list of user names and updates the UI reactively. Which is the best way to declare and update this list inside your ViewModel?
hard
A. class UserViewModel : ViewModel() {\n val users = MutableLiveData(emptyList())\n fun addUser(name: String) {\n users.value = users.value?.plus(name)\n }\n}
B. class UserViewModel : ViewModel() {\n val users = mutableListOf<String>()\n fun addUser(name: String) {\n users.add(name)\n }\n}
C. class UserViewModel : ViewModel() {\n var users = listOf<String>()\n fun addUser(name: String) {\n users += name\n }\n}
D. class UserViewModel : ViewModel() {\n val users = LiveData()\n fun addUser(name: String) {\n users.value = listOf(name)\n }\n}

Solution

  1. Step 1: Identify reactive data holder

    MutableLiveData<List<String>> allows UI to observe changes and update reactively.
  2. Step 2: Check update method correctness

    class UserViewModel : ViewModel() {\n val users = MutableLiveData<List<String>>(emptyList())\n fun addUser(name: String) {\n users.value = users.value?.plus(name)\n }\n} uses users.value?.plus(name) to add a user immutably and update LiveData, which is correct.
  3. Step 3: Review other options

    class UserViewModel : ViewModel() {\n val users = mutableListOf<String>()\n fun addUser(name: String) {\n users.add(name)\n }\n} uses mutableList but not LiveData, so UI won't update reactively. class UserViewModel : ViewModel() {\n var users = listOf<String>()\n fun addUser(name: String) {\n users += name\n }\n} uses var list but no LiveData. class UserViewModel : ViewModel() {\n val users = LiveData<List<String>>()\n fun addUser(name: String) {\n users.value = listOf(name)\n }\n} tries to instantiate LiveData directly, which is abstract and invalid.
  4. Final Answer:

    class UserViewModel : ViewModel() {\n val users = MutableLiveData<List<String>>(emptyList())\n fun addUser(name: String) {\n users.value = users.value?.plus(name)\n }\n} -> Option A
  5. Quick Check:

    Use MutableLiveData with immutable updates for reactive UI [OK]
Hint: Use MutableLiveData and update list immutably for UI updates [OK]
Common Mistakes:
  • Using mutableList without LiveData for UI data
  • Trying to instantiate LiveData directly
  • Modifying list without updating LiveData value
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard