As Android codebases scale, modularization is inevitable. We break down monolithic apps to achieve faster build times, separate team ownership, and isolate features.
However, many teams fall into a common trap: direct feature-to-feature dependencies.
If :feature:onboarding needs to trigger :feature:auth, developers often add a direct dependency. But what happens when :feature:auth needs to redirect back to onboarding, or share a common session state? You hit the dreading Circular Dependency compiler error.
To fix this, teams often resort to merging modules or writing messy reflection wrappers.
Here is the clean, enterprise-grade solution: The API vs. Implementation Module Separation.
The Core Concept: Dependency Inversion at Module Level
Instead of creating a single feature module, we split the feature into two separate Gradle modules:
-
:feature:auth:api(Lightweight interface module): Contains only public interfaces, DTOs, navigation entry points, and event states. It has no dependency on UI, Compose, or database layers. -
:feature:auth:impl(Concrete implementation module): Contains the actual UI screens, Compose layouts, view models, database helper engines, and internal Hilt modules. It implements the interfaces defined in the:apimodule.
:feature:onboarding (Feature UI)
│
▼ (Depends on API only)
:feature:auth:api (Public Interface) ◄─── (Implemented by) ─── :feature:auth:impl (Private UI)
Now, :feature:onboarding only needs to depend on the lightweight :feature:auth:api module. It calls the public interface, while the actual implementation (:feature:auth:impl) is injected dynamically at runtime.
Step-by-Step Implementation
1. Define the API Interface (:feature:auth:api)
The API module contains only standard Kotlin code and basic model dependencies. Here, we define the contract for other modules:
// Location: :feature:auth:api
interface AuthApi {
fun getAuthFlow(): Flow<UserSession?>
suspend fun logout()
}
2. Implement the Business Logic (:feature:auth:impl)
The implementation module depends on its corresponding API module and implements the interface:
// Location: :feature:auth:impl/build.gradle.kts
dependencies {
implementation(projects.feature.auth.api)
implementation(libs.hilt.android)
}
// Location: :feature:auth:impl/src/.../AuthApiImpl.kt
class AuthApiImpl @Inject constructor(
private val tokenStorage: TokenStorage,
private val database: AppDatabase
) : AuthApi {
override fun getAuthFlow(): Flow<UserSession?> = tokenStorage.observeSession()
override suspend fun logout() {
tokenStorage.clear()
database.clearAllTables()
}
}
3. Bind the Interface dynamically using Hilt
Inside the implementation module, define a Hilt module to bind the implementation to the interface. Because other modules request the AuthApi interface, Hilt will resolve it to the AuthApiImpl class at runtime:
// Location: :feature:auth:impl/src/.../AuthModule.kt
@Module
@InstallIn(SingletonComponent::class)
abstract class AuthModule {
@Binds
@Singleton
abstract fun bindAuthApi(impl: AuthApiImpl): AuthApi
}
Why this improves your Gradle builds
- Zero Circular Dependencies: Sibling feature modules can call each other's APIs without circular compiler cycles.
-
Faster Incremental Builds: If you modify a Compose layout inside
:feature:auth:impl, only that module compiles. Sibling modules (like onboarding) are completely bypassed because the API module (:feature:auth:api) hasn't changed. - Parallel Workflows: Teams can develop features in parallel. You can write your feature code using mock API implementations before the other team even begins writing their concrete implementation code.
📘 Master Android System Design & Architecture
If you want to master clean architecture, offline-first syncing, performance profiling, and dependency injection patterns, grab The Ultimate Android System Design & Tech Lead Bundle:
➡️ Get the Ultimate Tech Lead Bundle on Gumroad
The bundle includes the flagship System Design Playbook (26 pages) along with three premium bonuses: the 2026 Interview Question Bank, the Jetpack Compose Custom UI Cookbook, and the Android Gradle Optimization Cheat Sheet.
Top comments (0)