Model Mapping in Android
Lerne, warum du Datenmodelle an Schichtgrenzen konvertieren solltest. So vermeidest du, dass externe Formate deine gesamte App durchdringen.
In modernen Android-Apps fließen Daten durch mehrere Schichten: vom Netzwerk über die Datenbank bis zur UI. Jede Schicht hat andere Anforderungen an die Struktur dieser Daten. Model Mapping ist die Technik, Datenmodelle an diesen Schichtgrenzen aktiv umzuwandeln, anstatt ein einziges Modell durch die gesamte App zu schleifen.
Was ist das?
Model Mapping bedeutet, dass du für jede Schicht deiner App einen eigenen Datentyp definierst und ihn beim Übergang in die nächste Schicht explizit konvertierst. Die vier wichtigsten Modell-Typen in Android-Projekten sind:
- DTO (Data Transfer Object): Das Format, das eine externe API zurückschickt. Es spiegelt die Serverstruktur wider und enthält häufig JSON-Felder, die für die eigentliche App-Logik irrelevant sind.
- Entity: Die Repräsentation eines Datenbankeintrags, beispielsweise in Room. Sie enthält technische Details wie Primärschlüssel oder Fremdschlüssel-Spalten.
- Domain-Modell: Das reine Geschäftsobjekt. Es kennt weder Netzwerk- noch Datenbankdetails und bildet das Herzstück der Business-Logik.
- UI-Modell: Ein auf die Anzeige optimierter Typ, der zum Beispiel bereits formatierte Zeichenketten oder Zustandsflags enthält, die Compose direkt verarbeiten kann.
Das Ziel ist, jede Schicht unabhängig von den anderen weiterentwickeln zu können. Ändert die API ihr Schema, betrifft das nur die Mapper-Funktion und das DTO – nicht das ViewModel oder die Composables.
Wie funktioniert es?
Die offizielle Android-Architekturempfehlung beschreibt eine Drei-Schicht-Architektur: UI-Schicht, Domain-Schicht (optional) und Datenschicht. Model Mapping findet jeweils an den Grenzen zwischen diesen Schichten statt.
DTO → Domain-Modell geschieht im Repository. Sobald du Daten aus einer API holst, konvertierst du das DTO sofort in ein Domain-Modell, bevor du es nach oben weitergibst. Der Rest der App kennt das DTO dadurch gar nicht.
Entity → Domain-Modell läuft ebenfalls im Repository. Room liefert eine Entity; du übersetzt sie in ein Domain-Objekt, bevor du es an einen Use Case oder das ViewModel übergibst.
Domain-Modell → UI-Modell passiert im ViewModel. Es nimmt das saubere Domain-Objekt und baut daraus einen UI-State – zum Beispiel durch Formatierung von Datum oder Geldbetrag oder durch Berechnung von isLoading-Flags.
Kotlin macht dieses Mapping besonders handlich: Extension-Functions wie fun ArticleDto.toDomain(): Article halten den Konvertierungscode nah am Typ, ohne die ursprüngliche Klasse zu verunreinigen.
In der Praxis
Angenommen, du baust einen News-Feed. Die API liefert folgendes DTO:
data class ArticleDto(
val id: String,
val headline: String,
val body: String,
val publishedAt: String, // ISO-8601 String vom Server
val authorName: String
)
Dein Domain-Modell braucht keinen Raw-String für das Datum:
data class Article(
val id: String,
val headline: String,
val body: String,
val publishedAt: Instant,
val authorName: String
)
Und das UI-Modell bereitet alles direkt für Compose vor:
data class ArticleUiModel(
val id: String,
val headline: String,
val body: String,
val formattedDate: String, // z. B. "25. April 2026"
val authorName: String
)
Die zugehörigen Mapper-Functions:
fun ArticleDto.toDomain(): Article = Article(
id = id,
headline = headline,
body = body,
publishedAt = Instant.parse(publishedAt),
authorName = authorName
)
fun Article.toUiModel(formatter: DateTimeFormatter): ArticleUiModel = ArticleUiModel(
id = id,
headline = headline,
body = body,
formattedDate = formatter.format(publishedAt),
authorName = authorName
)
Typische Stolperfalle: Viele Entwicklerinnen und Entwickler verwenden das DTO direkt als Domain-Modell, um sich den Mapper zu sparen. Sobald die API ihr Schema ändert – ein Feldname wird umbenannt, ein Typ wechselt von String auf Long – musst du Änderungen durch die gesamte App jagen, inklusive ViewModel und Composables. Mit sauberem Mapping ist nur die Repository-Schicht und der eine Mapper betroffen. Noch subtiler: Wenn ein DTO-Feld null sein darf, weil der Server es so definiert, sollte dieses null niemals bis in die UI-Logik durchdringen. Der Mapper ist der ideale Ort, einen sinnvollen Fallback zu setzen.
Fazit
Model Mapping ist eine der unscheinbarsten, aber wirkungsvollsten Techniken in der Android-Architektur. Sie kostet dich initial etwas Tipparbeit, schützt dich aber dauerhaft vor teuren Kopplungsschäden. Geh jetzt in ein bestehendes Projekt und prüfe: Benutzt dein ViewModel direkt Typen aus dem Netzwerk-Layer? Wenn ja, hast du eine konkrete Stelle gefunden, an der ein Mapper sofort Verbesserungen brächte. Schreib anschließend einen Unit-Test für deinen neuen Mapper – er zeigt dir zuverlässig, ob alle Transformationen korrekt greifen, und gibt dir Sicherheit bei späteren API-Änderungen.