Java android architecture
Skill almasumdev/awesome-java-android-agent-skills/.github/skills/architecture/java-android-architecture
Curated agent skills, conventions, and workflows for building Java Android apps with AI coding agents.
npx -y skills add almasumdev/awesome-java-android-agent-skills --skill java-android-architectureAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Expert guidance on structuring a Java-based Android application using Clean Architecture, feature modularization, and dependency injection with Hilt. Use this when asked about project structure, module layout, or DI in a Java codebase.
SKILL.md
4.7 KB, ~1.1k tokens by cl100k_base, as published. Nobody here has run it
Java Android Clean Architecture & Modularization
Instructions
When designing or refactoring a Java-based Android app, follow Clean Architecture principles. Dependencies must flow inwards toward pure Java domain code. The repository standard is Java 17 with AndroidX + Hilt.
1. High-Level Layers
- Presentation Layer
- Responsibility: Rendering views and handling user input.
- Components:
Activity,Fragment,ViewModel(Jetpack),LiveData, adapters. - Dependencies: Domain interfaces only (UseCases or repository interfaces).
- Domain Layer (Pure Java)
- Responsibility: Business rules and domain entities.
- Components: UseCases (e.g.
GetArticles), immutable entities (preferrecords), repository interfaces. - Rule: MUST NOT import
android.*orandroidx.*. Keep under:domainmodule orcom.example.app.domain.
- Data Layer
- Responsibility: Fetching, caching, and persisting data.
- Components: Repository implementations, Retrofit services, Room DAOs, DTOs + mappers.
2. Package-by-Feature vs Package-by-Layer
For anything larger than a sample, prefer package-by-feature at the top level, with internal layering:
com.example.app/
├── core/ // shared: theme, errors, network, DI
├── di/ // Hilt @Module classes
├── features/
│ ├── articles/
│ │ ├── data/ // ArticleRepositoryImpl, ArticleApi, ArticleDao
│ │ ├── domain/ // Article (record), ArticleRepository, GetArticles
│ │ └── ui/ // ArticleListFragment, ArticleListViewModel
│ └── profile/
│ └── ...
└── App.java // @HiltAndroidApp
Package-by-layer (ui/, domain/, data/ at the root) is acceptable for small apps but does not scale past ~3 features.
3. Dependency Injection with Hilt
@HiltAndroidApp
public class App extends Application { }
@Module
@InstallIn(SingletonComponent.class)
public abstract class RepositoryModule {
@Binds
abstract ArticleRepository bindArticleRepository(ArticleRepositoryImpl impl);
}
@HiltViewModel
public class ArticleListViewModel extends ViewModel {
private final GetArticles getArticles;
@Inject
public ArticleListViewModel(GetArticles getArticles) {
this.getArticles = getArticles;
}
}
Never use service locators in production code. @Inject on the constructor is the default; @Provides modules are only for types you do not own.
4. Modularization Strategy
For apps with more than ~5 features, split into Gradle modules:
settings.gradle
├── :app // wiring, Application class, navigation host
├── :core:ui // common widgets, theme resources
├── :core:network // OkHttp, Retrofit, interceptors
├── :core:database // Room database + base DAOs
├── :feature:articles
│ ├── :feature:articles:api // public interfaces
│ └── :feature:articles:impl // implementation, UI
└── :domain // pure-Java module (no android plugin)
:domain uses apply plugin: 'java-library' so it cannot accidentally depend on Android types. Feature impl modules depend on feature api modules, never on each other.
5. Enforcing Architecture
Use com.tngtech.archunit:archunit-junit5 to fail the build on violations:
@AnalyzeClasses(packages = "com.example.app")
class ArchitectureTest {
@ArchTest
static final ArchRule domainHasNoAndroidDeps =
noClasses().that().resideInAPackage("..domain..")
.should().dependOnClassesThat()
.resideInAnyPackage("android..", "androidx..");
@ArchTest
static final ArchRule featuresDoNotDependOnEachOther =
noClasses().that().resideInAPackage("..features.articles..")
.should().dependOnClassesThat()
.resideInAPackage("..features.profile..");
}
Checklist
- Domain layer has zero
android.*/androidx.*imports (enforced by ArchUnit or a pure-Java Gradle module). - Repositories expose domain entities; never leak Retrofit
Responseor Room entities to the UI. -
ViewModels receive dependencies via@Injectconstructor, never via static singletons. - Features do not import sibling features; communication goes through
:coreor navigation. -
:domainmodule is ajava-librarymodule, not anandroid-library.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.