Sobes.tech
Junior

Tell me about Jetpack ViewModel.

sobes.tech AI

Answer from AI

ViewModel is a Jetpack component designed to store and manage UI-related data in a lifecycle-conscious way. Its main goal is to retain UI data during configuration changes, such as screen rotations, and to survive the lifecycle of an Activity or Fragment.

Features of ViewModel:

  • Data retention: Survives configuration changes and even Activity/Fragment death, restoring data upon recreation.
  • Separation of logic: Separates data preparation logic for UI from the UI itself (Activity/Fragment).
  • Lifecycle-aware: Tied to the lifecycle of an Activity or Fragment.
  • Memory leak prevention: Does not hold direct references to View, Lifecycle, or Activity/Fragment, preventing memory leaks.

How to use:

  1. Create a class inheriting from ViewModel.

    class MyViewModel : ViewModel() {
        private val _data = MutableLiveData<String>()
        val data: LiveData<String> = _data
    
        init {
            // Initialize data
        }
    
        fun fetchData() {
            // Data loading logic
            _data.value = "Loaded data"
        }
    
        override fun onCleared() {
            // Resource cleanup
            super.onCleared()
        }
    }
    
  2. Obtain an instance of ViewModel in an Activity or Fragment.

    class MyActivity : AppCompatActivity() {
        private lateinit var viewModel: MyViewModel
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
    
            viewModel.data.observe(this, Observer { newData ->
                // Update UI
            })
    
            viewModel.fetchData()
        }
    }
    
  3. Use ViewModelProvider.Factory to create ViewModel instances with dependencies.

    class MyViewModel(private val repository: MyRepository) : ViewModel() {
        // ...
    }
    
    class MyViewModelFactory(private val repository: MyRepository) : ViewModelProvider.Factory {
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
                @Suppress("UNCHECKED_CAST")
                return MyViewModel(repository) as T
            }
            throw IllegalArgumentException("Unknown ViewModel class")
        }
    }
    
    // In Activity/Fragment
    // val repository = MyRepository() // Dependency injection
    // viewModel = ViewModelProvider(this, MyViewModelFactory(repository)).get(MyViewModel::class.java)
    

Comparison with onSaveInstanceState():

Characteristic ViewModel onSaveInstanceState()
Configuration change survival Yes Yes (for small data volumes)
Process survival No (data lost after process termination) Yes (for small data volumes)
Data storage Objects, LiveData Bundle (primitives, Serializable, Parcelable)
Memory leaks No (when used correctly) Possible when holding references to Activity/View
Implementation complexity More complex for simple scenarios Simpler for simple scenarios

ViewModel helps create more resilient and easily testable applications by separating UI from data processing logic.