An architecture practice for separating data from UI. By extending the ViewModel
class and instantiating via the by viewModels()
delegate, data inside the ViewModel is automagically retained through configuration changes (Orientation, light/dark mode, etc.)
+--------------------------------+------------------------------------------+
| UI Responsibilities | `ViewModel` Responsibilities |
+--------------------------------+------------------------------------------+
| `Activity` and `Fragment` are | `ViewModel` is responsible for holding |
| responsible for drawing views | and processing all the data needed for |
| and data to the screen and | the UI. It should never access your view |
| responding to user events | hierarchy (like view binding object) or |
| | hold a reference to the activity or the |
| | fragment. |
+--------------------------------+------------------------------------------+
Sidenote: Delegates
Delegates: Property delegation in Kotlin helps you by handing off the getter-setter functionality to a different class. Defined using the
by
keyword. In this case, theviewModels
delegate is what does the retaining through configuration changes.kotlin var <property-name> : <property-type> by <delegate-class>() //For example: private val viewModel: GameViewModel by viewModels()
Backing Properties
The correct practice for giving a private property a public getter that still limits access to the actual value. The convention is to prefix the private property with _
private var _count = 0
val count: Int
get() = _count
Thus, a ViewModel
can hold the actual value, and the View
that holds the ViewModel
can access the property in a safe manner
Warning: Use this practice to ensure that mutable data inside your
ViewModel
is always private
ViewModel
's Lifecycle
The Android framework will keep the ViewModel
alive as long as the scope of the Activity
is alive, including a new instance of an Activity
reconnecting to an existing ViewModel
Sidenote: lateinit
In Kotlin, the lateinit
keyword is used to promise the compiler that despite not giving a variable an initial value, you will give it one before trying to access it (typically inside init
). Breaking this promise will cause the app to crash
Adjacent: MaterialAlertDialog
A dialog is a popup window in the middle of the screen. Use MaterialAlertDialogBuilder
to setup and configure the things that you want about the dialog, and calling show()
at the end. Some of the configuration options include:
- setTitle(String)
- setMessage(String)
- setCancelable(Boolean)
- setNegativeButton(String, DialogInterface.OnClickListener)
- setPositiveButton(String, DialogInterface.OnClickListener)
Adjacent: TextInputLayout
Error Options
Material text fields contain built in ways to show something wrong with a text field, using the isErrorEnabled
property in conjunction with error