close
close

Why use a well-structured architecture in Android?

Why use a well-structured architecture in Android?

The Android Operating System (AOSP) is designed to enhance the user experience by efficiently managing system resources. To maintain optimal performance, it can kill processes when necessary. If it “decides” to kill your process, there is little you can do to prevent it. Therefore, maintaining a consistent architecture is crucial to prevent data loss. Understanding the principle of separation of concerns is essential as you begin your Android architecture journey.

Separation of concerns

Separation of Concerns (SoC) is a principle that organizes code into separate layers, each representing a specific aspect of the application, such as the data layer, UI layer, and business logic layer. This structure improves code maintainability, readability, and comprehension, enabling a faster learning curve for newcomers. SoC also promotes code reusability and simplifies updates by allowing changes within individual layers without affecting others.

In the book Elements of Functional Programmingthe concept of separation of concerns is explored through several core topics:

  • Describe what needs to be calculated;
  • Organizing the calculation sequence into small steps;
  • Managing memory while calculating.

UI layer

The UI layer encompasses all aspects of the user interface and serves as the entry point to 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 separate layer, the Data Layer.

The UI state should not be updated directly within the UI components. Instead, a state holder should be used. One of the most well-known state holders on Android is the ViewModelThe . ViewModel Classes define the logic that is applied to events in the app and produces updated states as a result.

However, ViewModels, or viewholders, have a life cycle that extends beyond that of a Activity. They should not manage UI flow directly to avoid memory leaks. Furthermore, observables and flow collections should only be triggered to observe or collect data when the activity starts.

Low-level communication

As illustrated in Figure 1, the ViewModel is an integral part of the UI layer, responsible for responding to UI element interactions initiated by the user. For example, when a user clicks a button, an event is triggered that is passed to the ViewModelThe . ViewModel then processes the necessary logic and forwards the request to the Data Layer. After receiving a response, ViewModel updates the user interface with the new status. The updates in the data are observed or collected, using LiveData for observation or StateFlow for collection.

Image description

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 creating, storing, and modifying data.

The Data Layer consists of repositories—classes responsible for processing specific types of data. Each repository is responsible for:

  • Expose data only to the application;
  • Changing the data;
  • Resolving conflicts between data sources;
  • Integrate business logic.

Let’s see what this looks like in real life:

Here’s an example of how low-level communication works. The Activity must not directly manipulate the data. Instead, it must ViewModel to access data from the repository. The ViewModel gets a copy of the repository via dependency injection.

class BookListViewModel(
    private val repository: BookRepository
) : ViewModel() {
    private val _books = MutableLiveDataBookResponse>()
    val books: LiveDataBookResponse> = _books
    fun searchBooks(query: String) {
        viewModelScope.launch(Dispatchers.IO) {
             _books.postValue(repository.getBooks(query))
        }
    }
}
Go to full screen mode

Exit full screen

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.

Please feel free to share your thoughts or questions in the comments.
See you in the next topic!