Android Architecture Components
The Android Architecture Components library is a set of libraries provided by Google as part of the Android Jetpack, that is designed to help developers create robust, maintainable, and testable apps.
They are built to be lifecycle-aware, so they can automatically stop and start observing data based on the lifecycle state of an activity or fragment.
The Android Architecture Components library provides a set of best practices and guidelines for building apps that can be easily understood, maintained, and extended. It also provides a set of tools that make it easier to implement these best practices, such as the ViewModel
, LiveData
, Room
, etc.
The library includes several components that can be used to build an app’s architecture, such as:
- ViewModel: A class that is designed to store and manage UI-related data in a lifecycle-aware way. It allows data to survive configuration changes such as screen rotations.
- LiveData: A data holder class that can be observed within a given lifecycle. It’s designed to hold data that changes and notify observers when the data changes.
- Room: A persistence library that provides an abstraction layer over SQLite to allow for more robust database access while harnessing the full power of SQLite.
- Paging: A library that allows developers to easily load and display large sets of data from a database or network in a way that is efficient for the user and the device.
- WorkManager: A library that allows developers to schedule and manage background tasks in a way that is aware of the lifecycle of the app and the device.
- Navigation: A library that provides a simple, consistent API for navigation and deep linking in an app.
MutableLiveData and LiveData
LiveData
and MutableLiveData
are classes provided by the Android Architecture Components library that are used to hold and manage data in an Android app.
Here are some reasons why you might use LiveData and MutableLiveData:
- Lifecycle-aware: LiveData is aware of the lifecycle of the components that are observing it, this means that it will only update the UI when the activity or fragment is in a “resumed” state. This ensures that you do not update the UI when the activity or fragment is not visible, which can help prevent memory leaks and improve performance.
- Safe observer: LiveData will not notify its observer if the observer is in a different lifecycle state than the LiveData, this means that you do not need to worry about updating the UI when the activity or fragment is not visible.
- No memory leaks: Because LiveData is aware of the lifecycle of the components that are observing it, it can automatically remove observers when the activity or fragment is destroyed, this helps prevent memory leaks.
- Easy to test: Because LiveData is not tied to the Android framework, it can be easily tested in isolation from the UI.
- MutableLiveData: It’s a subclass of
LiveData
that allows you to modify the data stored in the object. MutableLiveData is useful when you need to update the data stored in the LiveData object. - Data sharing: LiveData and MutableLiveData can be used to share data between different parts of your app such as between activities, fragments, or even different modules. This allows you to easily share data between different parts of your app without having to manually pass data between them.
In summary, LiveData and MutableLiveData are powerful classes that make it easy to manage and share data in an Android app while ensuring that the data is only updated when the activity or fragment is in a “resumed” state. This can help improve performance, prevent memory leaks and make your code easier to test.
ViewModel & LiveData Example
MainActivityViewModel.kt class
/* Remember that ViewModel hold all UI data.*/
private const val TAG = "MainActivityViewModel"
class MainActivityViewModel : ViewModel() {
private val contactLiveData: MutableLiveData<MutableList<Contact>>
init {
Log.e(TAG, "init")
contactLiveData = MutableLiveData()
contactLiveData.value = createContacts()
}
fun getContacts(): LiveData<MutableList<Contact>> {
Log.e(TAG, "getContacts")
return contactLiveData
}
/*UI data*/
private fun createContacts(): MutableList<Contact> {
val contacts = mutableListOf<Contact>()
for (i in 1..200) {
contacts.add(Contact("Person #$i", i))
}
return contacts
}
}
In MainActivity.kt class
/* 02. ViewModel for screen rotation problem solved*/
val model = ViewModelProvider(this)[MainActivityViewModel::class.java]
model.getContacts().observe(this, Observer { contactSnapshot ->
// Update the UI
Log.e(TAG, "received contacts from the view model")
contactsList.clear()
contactsList.addAll(contactSnapshot)
contactsAdapter.notifyDataSetChanged()
})
Navigation Component
Navigation component from Android Jetpack to navigate from one fragment to another.
The findNavController(view)
method is used to find the NavController associated with the given view. Once the NavController is found, the navigate()
method is used to navigate to a specific destination fragment.
In this specific example, R.id.displayMapFragment
is passed as the parameter to the navigate()
method. This is the ID of the destination fragment that you want to navigate to. This ID should be defined in your navigation graph, which is a resource file that describes the navigation structure of your app.
Navigation also takes care of handling the back stack, so when the user presses the back button, the previous fragment will be displayed.
Navigation.findNavController(view).navigate(R.id.displayMapFragment)