A well-architected Android project structure with explanations.
August 22, 2024
Objective
To describe the Android project structure which focuses on separation of concern, modularization, scalability & Testability.
Kindly Note: This is only a structural explanation. Here, it doesn’t cover detailed classes.
Project Structure (Modularization):
App Module: This is your main application module responsible for assembling the other modules and presenting the UI.
Core Module: Contains common code shared across modules (utilities, extensions, constants).
Data Module: Handles data access (network, database, repositories).
Domain Module: Contains business logic (use cases, interactors).
Feature Modules: Each feature (e.g., login, profile, settings) gets its own module.
Architectural Pattern (Separation of Concerns):
We’ll use Model-View-ViewModel (MVVM) for clear separation:
Model: Represents data and business logic (entities, repositories in the Data module, use cases in the Domain module).
View: UI components (Activities, Fragments, Composables in the Feature and App modules).
ViewModel: Connects the View and Model, prepares data for display, and handles user interactions (in the Feature modules).
Example: News App
Let’s imagine a simple news app with two features: “Top Headlines” and “Search News.”
- Core Module (: core)
NetworkUtils.kt: Helper functions for network calls.
Constants.kt: API endpoints, keys, etc. - Data Module (:data)
NewsRepository.kt:
Fetches news data from a network API (using Retrofit).
Caches data locally (using Room database).
Provides a single source of truth for news data.
NewsApi.kt: Retrofit interface for the news API.
NewsDao.kt: Room DAO for accessing the local database. - Domain Module (:domain)
GetTopHeadlinesUseCase. kt: Fetches top headlines from the repository.
SearchNewsUseCase.kt: Searches for news based on a query, using the repository. - Feature Modules
:feature:topheadlines
TopHeadlinesViewModel. kt:
Uses GetTopHeadlinesUseCase to fetch data.
Exposes StateFlow for the UI to observe (list of news articles, loading state, errors).
TopHeadlinesScreen.kt (Composable):
Collects the StateFlow from the ViewModel.
Displays the list of headlines.
:feature:searchnews
SearchNewsViewModel. kt:
Uses SearchNewsUseCase to search for news.
Exposes StateFlow for the UI.
SearchNewsScreen.kt (Composable):
Collects the StateFlow from the ViewModel.
Provides a search bar and displays results. - App Module (:app)
MainActivity.kt: Sets up navigation between the two feature screens.
AppTheme.kt: Defines the app’s theme.
Dependency Injection (Hilt):
Use Hilt to provide dependencies:
Annotate NewsRepository with @Singleton to provide a single instance.
Inject GetTopHeadlinesUseCase and SearchNewsUseCase into their respective ViewModels.
Explanation:
Separation of Concerns: Each module has a clear responsibility, making the code maintainable and testable.
Modularization: Features are isolated, allowing for independent development and potential reuse.
Testability: Each layer can be tested in isolation (unit tests for use cases, UI tests for Composables).
Remember:
This is a simplified example. Real projects might have more complex data handling, error management, and navigation.
Adapt this structure to your specific app’s needs.
By following these principles, you’ll create a well-structured Android project that’s easy to understand, maintain, and scale.