Table of Contents
Overview of Architecture Components
Architecture Components in Android are a collection of libraries from Jetpack that help you build apps that are more robust, testable, and easier to maintain. They give you tools to separate concerns in your code, so your user interface code does not need to know how data is loaded or stored, and your data handling code does not need to know anything about Android views or activities.
In this chapter you get the big picture of what Architecture Components are and why they exist. Later chapters in this section focus specifically on ViewModel, LiveData, and the MVVM architecture pattern, so this chapter will introduce them only at a high level and will instead focus on the overall purpose and design ideas behind these libraries.
The Problem Architecture Components Solve
Without any structure, it is very easy for Android code to become tangled. Activities and fragments often end up doing too many things at once. They display the UI, respond to user input, load data from the network or database, and hold temporary state. This leads to several problems.
One problem is configuration changes. When the device rotates, the system destroys and recreates activities and fragments. If all your state and logic lives in an activity, you must manually save everything in onSaveInstanceState, and then restore it again. If you forget, data is lost.
Another problem is lifecycle awareness. UI controllers like activities and fragments have complex lifecycles. If you start long running work, for example a network request, and you do not cancel it when the UI is destroyed, you can leak memory or even crash the app when the work finishes and tries to update a non existent screen.
There is also the issue of testability. Code that directly depends on Android framework classes is harder to test in isolation. When activities and fragments contain networking, database, and business logic, your tests often need full Android instrumentation, which is slow and complex.
Finally, unstructured projects become hard to maintain and change. When responsibilities are mixed together, a new feature or change to one part of the system can break something else unexpectedly, because everything is coupled.
Architecture Components are designed to address all of these issues in a consistent way.
Core Ideas Behind Architecture Components
Architecture Components are based on a few key ideas that guide how you structure your Android apps.
One core idea is separation of concerns. Your code should be organized so that each part has a clear responsibility. UI code in activities and fragments is responsible for displaying data and forwarding user actions. Data and business logic live in separate classes. This makes each part simpler and less fragile.
Another idea is lifecycle awareness. Some components can observe lifecycle owners like activities and fragments, and they only perform work or send updates when it is safe. This reduces memory leaks and crashes. Instead of manually checking lifecycle states everywhere, you use classes that already understand them.
A third idea is persistence and survivability. Often you want some data or state to survive configuration changes such as screen rotation. A key part of these libraries is helping you hold and manage such state without rebuilding it from scratch each time.
The last major idea is reactive data flow. Data holders that can be observed, such as LiveData, let you declare that the UI reacts to changes in data. The UI observes the data, and when that data changes, the UI updates automatically. This is different from pushing data into views manually every time something changes.
Together these ideas encourage patterns where your UI is thin and passive, and the rest of the app is composed of testable, lifecycle aware components.
Main Architecture Components in Android
Android’s architecture libraries include several pieces that work well together.
View models are responsible for preparing and managing data for the UI. They survive configuration changes and do not reference views directly. They expose data for the UI to observe, usually through observable containers.
Live data is a lifecycle aware observable data holder. Activities and fragments can observe it, and they only receive updates while in an active lifecycle state. This helps avoid leaks and wasted work.
There are also navigation components, which manage in app navigation in a structured way, using a navigation graph and a controller that knows about the back stack. Although this course focuses on the basics, it is useful to know that navigation is part of the overall architecture story.
Room is a persistence library that sits on top of SQLite. It handles database access with type safe data access objects and integrates well with LiveData and coroutines. Room belongs to the data layer of your app.
WorkManager is a library that schedules and runs deferrable background work that must eventually execute, such as syncing data. It is aware of constraints like network and battery. While not strictly limited to architecture patterns, it often plays an important role in well structured apps.
Other libraries, such as DataStore for preferences like storage, and Paging for large lists, fit into this ecosystem by following similar principles of separation, lifecycle awareness, and testability.
In this course, the focus inside this section will be on ViewModel, LiveData, and how they come together in MVVM, because these are the building blocks you will use in almost every modern Android app.
Typical Layers in a Modern Android App
Architecture Components encourage you to organize your code into logical layers. There are different patterns, but many apps share a similar structure.
At the top you have the presentation layer. This includes activities, fragments, and often view models. Activities and fragments display the UI and forward user input to view models. View models hold UI related data and decide when to load or update it.
Below that you usually have a domain or business logic layer. In simple apps this layer might be very thin or even skipped, but in larger apps it contains use case classes that coordinate operations, such as loading and combining data from multiple sources and applying business rules.
At the bottom you have the data layer. This layer contains repositories that know where data comes from and how to fetch it, for example from a local database using Room or from a network API using Retrofit. Individual data sources, such as a remote data source or a local data source, live here as well.
The key point is that communication typically flows in one direction. UI components depend on view models, view models depend on repositories or use cases, and repositories depend on data sources like network services and databases.
Important rule: Upper layers may depend on lower layers, but lower layers should not depend on upper layers like activities or fragments. This direction keeps your code decoupled and easier to test.
Later when you learn MVVM, you will see how this layering lines up with that pattern.
Lifecycle Awareness and Safer Code
Lifecycle awareness is one of the most practical benefits of Architecture Components. Activities and fragments can move through many states, such as created, started, resumed, paused, stopped, and destroyed. If you do not coordinate your background work with these states, you might update a screen that is no longer visible, or hold references to destroyed views.
With lifecycle aware components, you can attach behavior to lifecycle owners in a safe way. For example, when UI objects observe a piece of LiveData, they only receive updates while in an active state, and they automatically stop observing when destroyed. You do not need to unregister listeners manually in many cases.
Some components also implement the LifecycleObserver concept, which lets you run code when certain lifecycle events occur. You can make helpers or managers that react to lifecycle changes without embedding that logic directly in your activities.
Because lifecycle logic is handled in a consistent library, your code is less likely to leak memory or crash due to accessing destroyed views.
State Management Across Configuration Changes
Configuration changes, like rotating the device or changing the system language, recreate activities and fragments. If you rely only on fields inside an activity, this recreation clears your state.
Architecture Components provide a better way to keep state that belongs to the UI but should survive such changes. The central tool for this is the view model, which has a lifecycle that is tied to the scope of the UI but is not destroyed during configuration changes.
From a practical perspective, this means expensive operations, such as loading data from a remote server or database, do not have to run again each time the device rotates. The UI controller simply reconnects to the existing view model and observes its state.
For simple values that must survive process death, you still use mechanisms like saved state handles or onSaveInstanceState. However, view models cover a large part of the everyday state that would otherwise be lost on rotation.
By combining view models with observable data holders, your app can recover smoothly after configuration changes, with less manual code.
Observability and Reactive Updates
One of the key patterns supported by Architecture Components is observable data that drives the UI. Instead of the UI actively pulling new values from your data sources, it subscribes to data streams and reacts when they change.
LiveData is an example of such a stream for UI data. It wraps a value and lets observers be notified when that value changes, while also respecting lifecycle states.
The reactive approach simplifies UI code. For instance, you can observe user profile data in a fragment. When the view model loads or updates that profile data, the LiveData emits a new value, and your observer updates the views. You do not need to manually connect every update operation back to the screen each time.
This style also fits very well with coroutines, flows, and other modern asynchronous tools, which you will encounter when dealing with background work and networking. Even if you later move from LiveData to other observable types, the idea of reactive data flow remains the same.
How Architecture Components Support MVVM
MVVM is an architectural pattern that divides the presentation layer into three roles. The model represents data and business logic, the view displays data and handles user input, and the view model connects the two.
Architecture Components provide built in support for this pattern. Activities and fragments take the role of the view. They are responsible for drawing the UI and routing user actions to the view model. They should avoid direct data loading or heavy logic.
The view model role is implemented with the ViewModel class. It holds LiveData or other observable data that the view observes. It also calls repositories or use cases to load or update data. Because the view model is lifecycle aware and survives configuration changes, it is well suited for coordinating the UI state.
Models in MVVM can be your data entities, repositories, and other classes that provide or transform data. Components like Room, Retrofit, and WorkManager live at this level, and they are unaware of the UI.
Later in this course, when you learn the MVVM chapter, you will see concrete examples of how these classes interact in practice. For now, it is enough to understand that Architecture Components are designed to fit naturally into MVVM, which is why they are common in modern Android apps.
Benefits for Testing and Maintenance
By separating concerns and reducing direct dependencies on Android framework classes, Architecture Components make your code easier to test.
View models can be tested as regular Kotlin classes, because they do not hold references to activities or views. You can feed them fake repositories, trigger actions, and assert that they update their observable data correctly. Repositories can also be tested in isolation by replacing network and database components with mock or fake implementations.
This style reduces the amount of instrumented tests that require a full Android environment, which are slower and more complex. You still need UI tests for some scenarios, but much of your logic can be covered with fast unit tests.
Maintenance also becomes easier. If you need to change how data is loaded, you modify the repository or data sources, while the UI and view models remain mostly unchanged. If you redesign the UI, you may only adjust the views and some bindings, while the data flow stays intact.
Clear architecture also makes it easier for new developers to understand the project. They can see where each kind of logic is supposed to live, and they can navigate the code by layers instead of hunting for behavior scattered across activities.
Using Architecture Components in New Projects
In modern Android Studio templates, some use of Architecture Components is often included or suggested by default. For example, templates may create a starter view model class or configure libraries from Jetpack.
When you start a new project, it is a good idea to plan how you will apply these components. Decide early that activities and fragments will stay focused on UI and navigation. Plan which data will live in view models and which logic will be moved into repositories or use cases.
As your app grows, add specific Architecture Components where they provide clear benefits. Use ViewModel to hold UI state, LiveData to observe data, Room for structured persistence, and WorkManager for background tasks that need guaranteed execution.
In the next chapters of this section you will work directly with ViewModel, LiveData, and the MVVM pattern. There you will see how the ideas described in this chapter are turned into concrete code in a simple but realistic Android app.