The Android Operating System (AOSP) is designed to enhance the user experience by managing system resources efficiently. To maintain optimal performance, it may terminate processes as needed. If it "decides" to kill your process, there's little you can do to prevent it. Therefore, maintaining a consistent architecture is crucial to avoid data loss. Understanding the principle of separation of concerns is essential as you embark on your journey with Android architecture.
Separation of Concerns
Separation of Concerns (SoC) is a principle that organizes code into distinct layers, each representing a specific aspect of the application, such as the data layer, UI layer, and business logic layer. This structure enhances code maintainability, readability, and comprehension, facilitating a quicker learning curve for newcomers. SoC also promotes code reusability and simplifies updates by allowing changes to be made within individual layers without impacting others.
In the book Elements of Functional Programming, the concept of separation of concerns is explored through several key topics:
- Describing what is to be computed;
- Organizing the computation sequencing into small steps;
- Managing memory during computation.
UI Layer
The UI layer encompasses all aspects of the user interface and serves as the entry point of the application. It contains everything the user needs to see and interact with. However, the data displayed in the UI layer is typically loaded from another distinct layer known as the Data Layer.
The UI state should not be updated directly within the UI components. Instead, it should utilize a state holder. One of the most well-known state holders on Android is the ViewModel
. The ViewModel
classes define the logic applied to events in the app and produce updated states as a result.
However, ViewModel
s, or view holders, have a lifecycle that extends beyond that of an Activity
. They should not manage any UI flow directly to avoid memory leaks. Additionally, observables and flow collections should only be activated to observe or collect data when the activity starts.
Layer Communication
As illustrated in the image below, the ViewModel
is an integral part of the UI Layer, responsible for responding to UI element interactions initiated by the user. For instance, when a user clicks a button, this triggers an event that is relayed to the ViewModel
. The ViewModel
then processes the necessary logic and forwards the request to the Data Layer. Upon receiving a response, the ViewModel
updates the UI with the new state. The updates in data are either observed or collected—using LiveData
for observation or StateFlow
for collection.
Data Layer
The Data Layer is responsible for managing all application data and business logic. This separation centralizes information management away from the UI Layer and facilitates unit testing. It specifies the protocols for data creation, storage, and modification.
The Data Layer consists of repositories—classes responsible for handling specific types of data. Each repository is responsible for:
- Exclusively exposing data to the application;
- Modifying the data;
- Resolving conflicts between data sources;
- Incorporating business logic.
Now let's see a bit of how this would look in real life:
Here’s an example of how layer communication works. The Activity
should not directly manipulate the data. Instead, it should use the ViewModel
to access data from the repository. The ViewModel
gets an instance of the repository through dependency injection.
class BookListViewModel(
private val repository: BookRepository
) : ViewModel() {
private val _books = MutableLiveData<BookResponse>()
val books: LiveData<BookResponse> = _books
fun searchBooks(query: String) {
viewModelScope.launch(Dispatchers.IO) {
_books.postValue(repository.getBooks(query))
}
}
}
Conclusion
Understanding and implementing the principle of separation of concerns is a crucial step in mastering Android development. By clearly defining and separating the responsibilities of different layers in your application, you can create code that is easier to maintain, test, and scale.
Feel free to share your thoughts or questions in the comments.
See you in the next topic!
Top comments (1)
Nice!