Guide to Android App Architecture: Google's Recommendation and Best Practices
Opening Note!
Among numerous discussions and debates on the Internet these days about the suitable architecture to follow and adapt, Google recently published a detailed blog to follow best practices while we are articulating the Android App. App architecture defines the backbone of scalable, maintainable, and high-performance Android apps. In this article, I am trying to curate the key principles from Google’s official guide, ideal for an app architecture. The purpose of this article is to clarify architectural patterns and highlight universal best practices.
Resources referenced:
Common factors to design architecture
1. Tackle various config changes
- An Android App must run on a wide variety of available devices in the global market i.e., phones, tablets, foldables, and various orientations.
 - Configuration changes like screen rotation, recreate activities. We must use ViewModels to preserve UI state and make sure to provide a smooth experience to users.
 - Hardcoding the dimensions while designing UI must be avoided to ensure responsive UI using responsive layouts and adaptive containers.
 
2. Android App’s Resource Constraints and Process Death
- Android devices have limitations in consideration of resource availability, and it may terminate App Processes in the background.
 - In case of process death, if we are not handing the app’s state properly, we will have to compromise with the current app state, it’ll be lost.
 - One very popular mechanism available SavedStateHandle in ViewModels to recover UI state and maintain user experience after unexpected process terminations.
 
3. Design for Variable Launch Conditions
- There are multiple ways, an app can be launched, when user tap on the launcher icon, via deeplink (form some web page or another app), or automatically when baclgroundn services starts it.
 - Because of above behaviour, Android App’s basic components like Activity, Service, Receiver, and Provider may be created or destroyed anytime in any order by the Operating System.
 - So, we should not keep any important data in Activity or Service variables, because we might loose it if the OS kills or restarts them. Instead, we can save and restore data properly using a rob app architecture like ViewModel, Repository, or persistent storage.
 
Layers of Separation: Structural Foundations
1. Separation of Concerns
This means we must be dividing our app into clear modules, so each module will hold its own specific responsibilities.
- UI Layer: It must only handleswhat the user visualizes on screen — like the buttons, text, and visuals. It also keeps short-term UI state (like if a button is selected).
 - Domain Layer (Optional): It must hold the main app logic, usecases basically. It fills the gap between the User’s expectation from the app and the way the app works.
 - Data Layer: It must handle the fetching and saving information — from various resources like the Internet (APIs), local databases, system services, or sensors.
 
Benefits:
- Clarity: Each class/function has a distinct home.
 - Isolation: Bugs remain contained within their respective layer.
 - Testing: Enables fast unit testing of business logic, minimal UI tests for rendering.
 
2. Single Source of Truth
- Each and every important piece of data in our app should be driven from only one source, which helps to avoid confusion and data mismatch.
 - For example, UI will be rendered taking the data from only the Database, not from the API source directly.
 - We should not be keeping multiple copies of the same data set at different places; instead, we should have only one clear source.
 
3. Unidirectional Data Flow (UDF)
In this pattern, data flows in only one direction, which makes the app’s flow clear and predictable.
- User actions or events (like clicking a button or typing text) start from the UI and move to the ViewModel.
 - The ViewModel updates the data and sends the new state back to the UI.
 
Because of this one-way flow, the UI only shows what the current state is — it doesn’t change data on its own.
This makes the app easier to understand, test, and debug. Architectural Patterns: Clean vs. Google-Recommended.                              
  
- Clean Architecture keeps business logic isolated, enabling faster changes to data sources without affecting core logic.
 - Google’s recommended structure is pragmatic, suitable for small to medium projects.
 - For apps expected to scale past 100k lines or for teams >5, use a distinct Domain Layer.
 
Data Models: Driving UI and Persisting State
- UI should reflect persistent models (local DB, API, Preferences) but not every fleeting state needs full persistence.
 - For temporary UI states (e.g., dialog visibility), use ViewModel’s SavedStateHandle instead of local DB.
 
Events, Actions, and State: Clarity in Communication
- State: Persistent values (e.g., isLoading, data).
 - Actions: UI → ViewModel communications (button clicks, text changes).
 - Events: One-time ViewModel → UI notifications (navigations, error snackbars).
 - Not all UI events should become persistent state — avoid repeatable actions (e.g., error snackbar after screen rotation).
 
If you have reached till here, hoping you found this blog useful 🙌🏻. Kindly share your valuable feedback/suggestions with me on below links.
EmailId: vikasacsoni9211@gmail.com
LinkedIn: https://www.linkedin.com/in/vikas-soni-052013160/
Happy Learning ❤️
Comments
Post a Comment