Modulabhängigkeiten verwalten
Den Abhängigkeitsgraphen sauber und azyklisch halten
Modulabhängigkeiten verwalten ist eine kostenlose Android Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Android Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Android Academy-Kurs umfasst insgesamt 4 Lektionen.
Der Abhängigkeitsgraph
Jedes Modul legt fest, von welchen anderen Modulen es abhängt. Zusammen bilden diese Abhängigkeiten einen Abhängigkeitsgraphen. Ein gesunder Graph ist ein DAG (gerichteter azyklischer Graph): Die Abhängigkeiten zeigen in eine Richtung und bilden niemals eine Schleife.
In dieser Lektion lernen Sie, Abhängigkeiten sauber zu deklarieren, die richtige Gradle-Konfiguration auszuwählen, Versionen gemeinsam zu nutzen und Zyklen zu verhindern.
Eine Modulabhängigkeit deklarieren
Sie fügen eine Abhängigkeit zu einem anderen Modul mit project(":path:to:module") innerhalb des dependencies-Blocks hinzu. Der Pfad bildet die Ordnerstruktur ab und entspricht dem, was Sie in settings.gradle.kts deklariert haben.
// feature/profile/build.gradle.kts
dependencies {
implementation(project(":core:data"))
implementation(project(":core:designsystem"))
implementation(project(":core:model"))
}implementation vs api
Die gewählte Konfiguration legt fest, was an abhängige Module durchscheint:
implementation: Die Abhängigkeit ist privat. Module, die von Ihrem Modul abhängen, können sie nicht sehen. Dies ist die Standardwahl.api: Die Abhängigkeit wird erneut veröffentlicht (transitiv). Verwenden Sie dies nur, wenn Ihre öffentlichen Typen aus dieser Abhängigkeit stammen.
Bevorzugen Sie fast immer implementation – dadurch werden Builds schneller, weil eine Änderung an einer verborgenen Abhängigkeit keine Neukompilierung der abhängigen Module erzwingt.
// core/data/build.gradle.kts
dependencies {
// Repository signatures return :core:model types,
// so consumers need to SEE it -> api
api(project(":core:model"))
// Network is an internal detail -> implementation
implementation(project(":core:network"))
}Warum implementation Builds beschleunigt
Mit implementation weiß Gradle, dass eine Änderung an einer verborgenen Abhängigkeit die öffentliche ABI des Moduls nicht beeinflussen kann. Daher müssen abhängige Module nicht neu kompiliert werden. Bei api wirkt sich eine Änderung auf alle transitiv abhängigen Module aus.
Faustregel: Eine Abhängigkeit gehört nur dann in api, wenn sie in den öffentlichen Typen des Moduls vorkommt (Rückgabetypen, öffentliche Parameter). Andernfalls verwenden Sie implementation.
// Public -> needs api
fun observeUser(): Flow<User> // Flow and User leak out
// Internal -> implementation is enough
private val client: OkHttpClient // never exposedVersionen zentralisieren: Der Version Catalog
Bei vielen Modulen möchten Sie Bibliotheksversionen nicht überall wiederholen. Gradles Version Catalog (gradle/libs.versions.toml) definiert Versionen und Aliase einmalig. Jedes Modul verwendet denselben Alias.
# gradle/libs.versions.toml
[versions]
compose-bom = "2024.09.00"
retrofit = "2.11.0"
[libraries]
compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }Den Catalog in einem Modul verwenden
Module greifen dann über den generierten libs-Accessor auf Bibliotheken zu. Keine Versionsnummern in der Build-Datei zu haben bedeutet, dass Aktualisierungen an einer einzigen Stelle erfolgen.
// core/network/build.gradle.kts
dependencies {
implementation(platform(libs.compose.bom))
implementation(libs.retrofit)
}Die Todsünde: Zyklen
Ein Zyklus liegt vor, wenn Modul A von B abhängt und B direkt oder über eine Kette wieder von A abhängt. Gradle verweigert den Build bei einer zirkulären Abhängigkeit. Außerdem weist ein Zyklus auf ein Designproblem hin: Die Grenze zwischen den beiden Modulen ist falsch gezogen.
// :feature:cart -> implementation(project(":feature:checkout"))
// :feature:checkout -> implementation(project(":feature:cart"))
//
// Gradle error:
// Circular dependency between the following tasks:
// :feature:cart:compile -> :feature:checkout:compile -> :feature:cart:compileEinen Zyklus auflösen
Um einen Zyklus aufzubrechen, extrahieren Sie den gemeinsam genutzten Teil in ein weiter unten liegendes Modul, von dem beide Module abhängen können. Wenn zwei Features die Daten des jeweils anderen benötigen, gehört dieser gemeinsame Vertrag in den Core, nicht in eines der beiden Features.
Dadurch wird der Abwärtsfluss wiederhergestellt: Beide Features zeigen nach unten auf den Core, und der Core zeigt niemals zurück nach oben.
// Before: cart <-> checkout (cycle)
// After: cart -> :core:order <- checkout
// core/order/OrderContract.kt
data class Order(val items: List<CartItem>, val total: Double)
// feature/cart -> implementation(project(":core:order"))
// feature/checkout-> implementation(project(":core:order"))Inversion: Von Abstraktionen abhängen
Manchmal benötigt ein Modul auf niedriger Ebene Verhalten, das weiter oben liegt. Statt nach oben zu verweisen, definieren Sie eine Schnittstelle im unteren Modul und lassen das höhere Modul die Implementierung über Dependency Injection bereitstellen. Das ist Dependency Inversion.
// core/analytics defines the contract
interface AnalyticsLogger {
fun log(event: String)
}
// :app provides the real implementation and injects it down
@Module
@InstallIn(SingletonComponent::class)
object AnalyticsModule {
@Provides
fun logger(impl: FirebaseAnalyticsLogger): AnalyticsLogger = impl
}Den Graphen visualisieren und absichern
Sie können Gradle anweisen, den Modulgraphen auszugeben oder darzustellen, und sogar einen Test hinzufügen, der den Build fehlschlagen lässt, wenn eine unerlaubte Abhängigkeit auftaucht (zum Beispiel ein Core-Modul, das von einem Feature abhängt). Tools wie das module-graph-Plugin erzeugen automatisch ein Diagramm.
# Print the project structure
./gradlew projects
# Inspect why :feature:home pulls in a library
./gradlew :feature:home:dependencies --configuration debugRuntimeClasspathEin sauberes, azyklisches Beispiel
Hier sehen Sie einen gesunden Graphen. Lesen Sie ihn von oben nach unten: Kein Pfeil zeigt jemals zurück nach oben, und keine zwei Module zeigen aufeinander. Genau das ist Ihr Ziel.
// :app
// -> :feature:home -> :core:data -> :core:network -> :core:model
// -> :feature:profile -> :core:data -> :core:database -> :core:model
// -> :core:designsystem
//
// Every path ends at :core:model. No cycles. Builds in parallel.Kurze Überprüfung
Ihr Modul :core:network verwendet OkHttpClient nur intern – es erscheint in keiner öffentlichen Funktionssignatur. Welche Gradle-Konfiguration sollten Sie verwenden, um die OkHttp-Abhängigkeit zu deklarieren?
Zusammenfassung: Modulabhängigkeiten verwalten
Sie haben gelernt, den Modulgraphen gesund zu halten:
- Deklarieren Sie Modulabhängigkeiten mit
project(":path"). - Verwenden Sie standardmäßig
implementation; nutzen Sieapinur für Typen in Ihrer öffentlichen Oberfläche. - Zentralisieren Sie Versionen in einem Version Catalog (
libs.versions.toml). - Erzeugen Sie niemals Zyklen – Gradle weist sie zurück. Brechen Sie sie auf, indem Sie gemeinsamen Code nach unten extrahieren oder die Abhängigkeit mit Schnittstellen umkehren.
Als Nächstes verbinden Sie Features über die Navigation miteinander, ohne sie eng zu koppeln.
Häufig gestellte Fragen
Ist die Lektion „Modulabhängigkeiten verwalten“ kostenlos?
Ja — der vollständige Text von „Modulabhängigkeiten verwalten“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Android Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Android Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Modulabhängigkeiten verwalten“?
Den Abhängigkeitsgraphen sauber und azyklisch halten Du übst Android Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Android Academy zu starten?
Keine Vorkenntnisse erforderlich. Android Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.
Wie lange dauert die Lektion „Modulabhängigkeiten verwalten“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Android Academy-Lektion Code schreiben und ausführen?
Ja. Jede Android Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Warum modularisieren?
- Feature- und Core-Module
- Modulabhängigkeiten verwalten
- Navigation über Module hinweg