Skip to content

Android ViewModel and LiveData Explained - Complete Jetpack Guide

DodaTech Updated 2026-06-29 3 min read

In this tutorial, you'll learn Android ViewModel and LiveData for managing UI data through configuration changes and lifecycle events.

What You'll Learn

Android ViewModel and LiveData for managing UI data through configuration changes and lifecycle events — ViewModel and LiveData prevent data loss on rotation, eliminate memory leaks, simplify inter-fragment communication, and make code testable.

Why It Matters

ViewModel and LiveData prevent data loss on rotation, eliminate memory leaks, simplify inter-fragment communication, and make code testable.

Real-World Use

A form-filling app uses ViewModel to hold draft data across fragment navigations and rotations. LiveData updates a progress indicator when saving. The ViewModel is unit-tested without an emulator.

Learning Path

flowchart LR
    [Activity Lifecycle] --> [ViewModel & LiveData] --> [Coroutines] --> [Navigation]
    style 2 fill:#4CAF50,color:#fff

Basic ViewModel with LiveData

class CounterViewModel : ViewModel() {
    private val _count = MutableLiveData(0)
    val count: LiveData<Int> = _count
    fun increment() { _count.value = (_count.value ?: 0) + 1 }
}
class CounterActivity : AppCompatActivity() {
    private val viewModel: CounterViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel.count.observe(this) { value ->
            findViewById<TextView>(R.id.counterText).text = "Count: $value"
        }
    }
}

Expected output: The counter survives rotation because the ViewModel scopes to the activity lifecycle.

LiveData vs StateFlow

// StateFlow approach (recommended for new projects)
class StateFlowViewModel : ViewModel() {
    private val _data = MutableStateFlow<String?>(null)
    val data: StateFlow<String?> = _data.asStateFlow()
    fun load() { viewModelScope.launch { _data.value = repository.fetch() } }
}
// In Fragment
viewLifecycleOwner.lifecycleScope.launch {
    viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.data.collect { value ->
            // Update UI
        }
    }
}

Expected output: StateFlow provides a modern, lifecycle-aware alternative to LiveData with stronger Kotlin Flow integration.

Shared ViewModel Across Fragments

class SharedViewModel : ViewModel() {
    private val _selectedItem = MutableLiveData<Item?>()
    val selectedItem: LiveData<Item?> = _selectedItem
    fun selectItem(item: Item) { _selectedItem.value = item }
}
class ListFragment : Fragment() {
    private val viewModel: SharedViewModel by activityViewModels()
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        binding.recyclerView.adapter = ItemAdapter { item -> viewModel.selectItem(item) }
    }
}

Expected output: Both ListFragment and DetailFragment share the same ViewModel instance scoped to their parent activity.

Common Errors

  1. LiveData not triggering - wait until lifecycle is at least STARTED
  2. ViewModelProvider.Factory not provided - custom factory needed for ViewModels with constructor parameters
  3. StateFlow initial value consumed late - use drop(1) for future-only emissions
  4. Activity-scoped ViewModel in DialogFragment - scope to dialog lifecycle instead
  5. Memory leak from LifecycleObserver - use viewLifecycleOwner in fragments, not this

Practice Questions

  1. How does ViewModel survive configuration changes?

  2. What is the difference between map and switchMap transformations?

  3. When would you choose StateFlow over LiveData?

  4. How do you share data between two fragments in the same activity?

  5. Why use viewLifecycleOwner instead of this for LiveData observations in fragments?

Challenge

Build a multi-step checkout form with 3 fragments (Shipping, Payment, Review) sharing one ViewModel. Each fragment updates its section. Survive rotation without losing form data.

Real-World Task

Implement an event bus using SharedFlow: create an EventBus Singleton with SharedFlow. Post events from any ViewModel and collect them in navigation or analytics observers.

Frequently Asked Questions

{{< faq question="Can a ViewModel hold an Activity reference?">}} Never. ViewModels can outlive Activities. Use AndroidViewModel for Application context or SavedStateHandle. {{< /faq >}}

{{< faq question="Is LiveData a reactive stream?">}} Yes, but lifecycle-aware. It only emits when the Observer is active (STARTED or RESUMED). {{< /faq >}}

{{< faq question="Should I still use LiveData in new projects?">}} Prefer StateFlow/SharedFlow with collectLatest/repeatOnLifecycle for new projects. LiveData is simpler but less flexible. {{< /faq >}}

Security Tip: Never expose sensitive data through LiveData/StateFlow that could be observed by background processes. Use distinctUntilChanged() to avoid re-emitting unchanged values.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro