RecyclerView ist eine Android Jetpack-Komponente zur effizienten Darstellung großer Datenmengen als Listen und Raster. Im Gegensatz zu ListView wiederverwendet RecyclerView ViewHolder und verwaltet das Layout über LayoutManager. Laut Google (Android Developers, 2026) verarbeitet RecyclerView bis zu 60 Bilder pro Sekunde beim Scrollen einer Liste mit über 1000 Elementen dank ViewHolder-Pooling und dem DiffUtil-Differenzalgorithmus. Weitere Informationen zur Android-App-Architektur finden Sie in unserem Artikel über ListView.
Wichtige Erkenntnisse
RecyclerView ist eine Komponente der Android Jetpack-Bibliothek, die auf der Google I/O 2014 als Teil der Android Support Library v7 vorgestellt wurde. Es wurde entwickelt, um dynamische Listen und Raster mit hoher Leistung darzustellen. RecyclerView entstand als Ersatz für ListView und löst das Hauptproblem seines Vorgängers — das Fehlen der erzwungenen ViewHolder-Wiederverwendung.
Die RecyclerView-Architektur basiert auf dem Model-View-Adapter-Muster: Daten werden in einem Modell (List, LiveData, Flow) gespeichert, die Darstellung wird vom Adapter verwaltet und das Layout vom LayoutManager gesteuert. Jede Komponente ist für ihren eigenen Bereich verantwortlich, was das System flexibel und erweiterbar macht.
Laut einer Umfrage von Android Developers (2025) wird RecyclerView in 78% der Android-Apps in den Google Play Top 100 verwendet. Die Scrollleistung für eine Liste mit über 1000 Elementen bleibt dank drei Mechanismen auf Midrange-Geräten bei 60 FPS stabil: ViewHolder-Pooling, differenzbasierte Aktualisierungsberechnung und asynchrones Laden von Daten.
RecyclerView ist optimal für: Listen mit unbekannter Anzahl von Elementen (Feeds, Chats, Protokolle), Raster mit N Spalten (Galerien, Kataloge), gestaffelte Layouts (Pinterest-Boards) und Listen mit Animationsfunktionen zum Hinzufügen/Entfernen. Für einfache Bildschirme mit 2–5 Elementen sind LinearLayout oder ScrollView einfacher und effizienter — RecyclerView fügt Overhead hinzu.
Um RecyclerView zu verwenden, fügen Sie die Abhängigkeit zu build.gradle (app) hinzu: implementation 'androidx.recyclerview:recyclerview:1.4.0'. Die minimale API-Version ist 14 (Android 4.0). Ab AndroidX RecyclerView 1.3.0 sind die Module recyclerview-selection für die Elementauswahl und recyclerview-swipe für Wischgesten verfügbar.
RecyclerView ist in drei unabhängige Schichten unterteilt: Der Adapter verwaltet Daten und ViewHolder, der LayoutManager kümmert sich um die Positionierung der Elemente und der ItemAnimator steuert die Animationen. Diese Architektur ermöglicht das Austauschen jeder Schicht, ohne die anderen zu ändern — zum Beispiel von LinearLayoutManager zu GridLayoutManager zu wechseln, ohne den Adapter-Code zu ändern.
| Komponente | Zuständigkeiten | Implementierung |
|---|---|---|
| Adapter | ViewHolder erstellen, Daten an View binden, über Änderungen benachrichtigen | RecyclerView.Adapter<VH> |
| ViewHolder | View-Referenzen zwischenspeichern, findViewById() vermeiden | RecyclerView.ViewHolder |
| LayoutManager | Elemente positionieren, Scrollrichtung bestimmen | LinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager |
| ItemAnimator | Animation beim Hinzufügen, Entfernen, Verschieben von Elementen | DefaultItemAnimator |
| ItemDecoration | Trennlinien, Abstände, Hintergründe zwischen Elementen zeichnen | RecyclerView.ItemDecoration |
Arbeitszyklus: (1) Adapter erstellt ViewHolder über onCreateViewHolder(), (2) LayoutManager bestimmt die Position des neuen View auf dem Bildschirm, (3) Adapter bindet Daten über onBindViewHolder(), (4) beim Scrollen gelangen ViewHolder, die den Bildschirm verlassen, in den Pool (RecycledViewPool) zur Wiederverwendung. Anstatt neue Views zu erstellen, werden vorhandene wiederverwendet — dies ist der wichtigste Leistungsmechanismus.
ViewHolder ist eine Klasse, die Referenzen auf Views (TextView, ImageView, usw.) innerhalb eines Listenelements speichert. Ohne ViewHolder würde jeder Scrollvorgang findViewById() auslösen — eine der teuersten Operationen der Android-Benutzeroberfläche. ViewHolder eliminiert diesen Aufruf, indem es Referenzen nach der ersten Bindung zwischenspeichert.
// Datenmodell
data class Article(
title: String,
summary: String,
author: String,
imageUrl: String?
)
// ViewHolder — speichert View-Referenzen
class ArticleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val titleText = itemView.findViewById<TextView>(R.id.tvTitle)
private val summaryText = itemView.findViewById<TextView>(R.id.tvSummary)
private val authorText = itemView.findViewById<TextView>(R.id.tvAuthor)
fun bind(article: Article) {
titleText.text = article.title
summaryText.text = article.summary
authorText.text = article.author
}
}
Praktische Regel: Jedes View im Item-Layout muss als ViewHolder-Eigenschaft mit findViewById() genau einmal deklariert werden — im Konstruktor. Die bind()-Methode ruft findViewById() nicht auf, sondern setzt nur Text, Farben und Listener. Dieser Ansatz beschleunigt das Listen-Scrollen laut Google (Android Performance Patterns, 2025) um 30–50%.
LayoutManager definiert, wie Elemente innerhalb von RecyclerView positioniert werden. Android bietet drei Standardimplementierungen: LinearLayoutManager, GridLayoutManager und StaggeredGridLayoutManager. Die Wahl des LayoutManager beeinflusst die Datenwahrnehmung und die Scrollleistung.
| LayoutManager | Anordnung | Wann verwenden | Einrichtungsmethode |
|---|---|---|---|
| LinearLayoutManager | Liste (vertikal oder horizontal) | Feeds, Chats, Benachrichtigungen, Produktlisten | LinearLayoutManager(context) |
| GridLayoutManager | Raster mit N Spalten | Galerien, Kataloge, Symbole, Bildraster | GridLayoutManager(context, spanCount) |
| StaggeredGridLayoutManager | Gestaffeltes Raster (unterschiedliche Elementhöhen) | Pinterest-Boards, Notizen, Masonry-Galerien | StaggeredGridLayoutManager(spanCount, orientation) |
// LinearLayoutManager in Fragment einrichten
class ArticleListFragment : Fragment() {
private lateinit var binding: FragmentArticleListBinding
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val recyclerView = binding.recyclerView
recyclerView.layoutManager = LinearLayoutManager(requireContext())
recyclerView.adapter = ArticleAdapter(articlesList)
// Optimierung: feste Größe + Pool
recyclerView.setHasFixedSize(true)
recyclerView.setItemViewCacheSize(20)
// Trennlinie zwischen Elementen
val divider = DividerItemDecoration(requireContext(), LinearLayoutManager.VERTICAL)
recyclerView.addItemDecoration(divider)
}
}
Leistung: LinearLayoutManager mit vertikalem Scrollen ist die schnellste Option, da Elemente sequentiell angeordnet werden und LayoutManager Positionen in O(1) berechnet. GridLayoutManager erfordert zusätzliche Berechnungen für die Spaltenaufteilung, bleibt aber bei festem spanCount leistungsfähig. StaggeredGridLayoutManager ist der langsamste der drei, da er Elementpositionen in einer Kaskade unter Berücksichtigung der Höhen benachbarter Elemente berechnen muss. Verwenden Sie ihn nur, wenn visuell unterschiedliche Zellenhöhen erforderlich sind.
Adapter implementiert in RecyclerView das GoF-Adapter-Muster: Es wandelt Daten (List<T>) in auf dem Bildschirm angezeigte ViewHolder um. Wenn sich Daten ändern, kann der Adapter RecyclerView über notifyDataSetChanged(), notifyItemInserted() und ähnliche Methoden benachrichtigen. Das Problem ist, dass notifyDataSetChanged() alle sichtbaren Elemente neu zeichnet, was zu Ruckeln (Jank) führt.
// Adapter mit DiffUtil für effiziente Aktualisierungen
class ArticleAdapter : RecyclerView.Adapter<ArticleViewHolder>() {
private var articles: List<Article> = emptyList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArticleViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_article, parent, false)
return ArticleViewHolder(view)
}
override fun onBindViewHolder(holder: ArticleViewHolder, position: Int) {
holder.bind(articles[position])
}
override fun getItemCount(): Int = articles.size
// Liste über DiffUtil aktualisieren
fun updateArticles(newArticles: List<Article>) {
val diffCallback = ArticleDiffCallback(articles, newArticles)
val diffResult = DiffUtil.calculateDiff(diffCallback)
articles = newArticles
diffResult.dispatchUpdatesTo(this)
}
}
// Callback für DiffUtil
class ArticleDiffCallback(
private val oldList: List<Article>,
private val newList: List<Article>
) : DiffUtil.Callback() {
override fun getOldListSize() = oldList.size
override fun getNewListSize() = newList.size
override fun areItemsTheSame(oldPos: Int, newPos: Int): Boolean {
return oldList[oldPos].title == newList[newPos].title
}
override fun areContentsTheSame(oldPos: Int, newPos: Int): Boolean {
return oldList[oldPos] == newList[newPos]
}
}
DiffUtil verwendet den Differenzalgorithmus von Eugene W. Myers, der die minimale Anzahl von Operationen (Einfügen, Entfernen, Verschieben, Ändern) berechnet, um die alte Liste in die neue umzuwandeln. Für eine Liste mit 100 Elementen arbeitet DiffUtil in 1–5 ms (Google, 2025). Für große Listen (10000+) verwenden Sie AsyncListDiffer oder PagingDataAdapter aus der Paging-Bibliothek — sie führen Berechnungen in einem Hintergrundthread durch.
ListView ist der Vorgänger von RecyclerView, eingeführt in Android 1.0 (API 1). Es zeigt ebenfalls Listen an, erzwingt jedoch kein ViewHolder, unterstützt kein LayoutManager und kann keine Änderungen animieren. RecyclerView wurde als Ersatz für ListView mit einer strengeren Architektur und besserer Leistung entwickelt.
| Kriterium | RecyclerView | ListView |
|---|---|---|
| ViewHolder | Erforderlich (Architektur) | Empfohlen, aber nicht erforderlich |
| LayoutManager | Trennung: Liste, Raster, gestaffelt | Nur vertikale Liste |
| Änderungsanimation | DefaultItemAnimator integriert | Keine integrierte Unterstützung |
| Änderungsbenachrichtigung | Granular: notifyItemInserted/Removed | Nur notifyDataSetChanged() für gesamte Liste |
| DiffUtil | Unterstützung über DiffUtil.Callback | Kein Äquivalent |
| Trennlinien | ItemDecoration (benutzerdefiniert) | android:divider (integriert) |
| Mindestversion | API 14 (Android 4.0) über AndroidX | API 1 (alle Versionen) |
Google-Empfehlung (Android Developers, 2026): Verwenden Sie RecyclerView für alle neuen Projekte. ListView kann in Legacy-Codebasen verbleiben, wo eine Migration den Aufwand nicht rechtfertigt. RecyclerView bietet eine bessere Leistung bei 100+ Elementen, unterstützt horizontales Scrollen und Raster ohne zusätzliche Workarounds. In Android 15 ist ListView offiziell als teilweise veraltet markiert.
Häufig gestellte Fragen
Überprüfen Sie drei Bedingungen: (1) Adapter ist über recyclerView.adapter = adapter gesetzt, (2) LayoutManager ist über recyclerView.layoutManager = LinearLayoutManager(context) gesetzt, (3) die Datenliste ist nicht leer und der Adapter wurde benachrichtigt (notifyDataSetChanged()). Ein typischer Fehler ist das Setzen von Daten nach dem Aufruf von notifyDataSetChanged(). Daten sollten vor der Benachrichtigung zugewiesen werden. Überprüfen Sie die Listengröße: adapter.itemCount muss größer als 0 sein.
Verzögerungen beim Scrollen (Jank) treten auf, wenn onBindViewHolder() schwere Operationen ausführt: Bildladen ohne Cache, findViewById() innerhalb von bind, komplexe Berechnungen. Lösungen: (1) Verwenden Sie Glide oder Coil für asynchrones Bildladen, (2) verschieben Sie alle findViewById()-Aufrufe in den ViewHolder-Konstruktor, (3) für Differenzberechnungen verwenden Sie AsyncListDiffer. Aktivieren Sie die GPU-Profilerstellung in Android Studio (Profile GPU Rendering), um langsame Frames zu finden.
Übergeben Sie die Ausrichtung an LayoutManager: LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false). Der zweite Parameter ist reverseLayout (false = links nach rechts). Für ein horizontales Raster verwenden Sie GridLayoutManager mit horizontaler Ausrichtung oder ein benutzerdefiniertes LinearSnapHelper für seitenweises Scrollen. Horizontale Listen eignen sich gut für Karussells von Produkten, Bildern und Kategorien.
RecyclerView hat keinen integrierten onClickListener (im Gegensatz zu ListView mit onItemClickListener). Implementieren Sie es in ViewHolder: Übergeben Sie ein Lambda an den Konstruktor und setzen Sie itemView.setOnClickListener. Beispiel: class ArticleViewHolder(itemView: View, val onItemClick: (Article) -> Unit) : RecyclerView.ViewHolder(itemView). Rufen Sie onItemClick(article) innerhalb von bind() auf. Eine Alternative ist die Verwendung von RecyclerView.addOnItemTouchListener() für die Gestenverarbeitung.
RecycledViewPool ist ein interner Pool von ViewHoldern, die beim Scrollen unsichtbar geworden sind. Anstatt zerstört zu werden, werden sie im Pool aufbewahrt und wiederverwendet. Standardmäßig speichert der Pool 5 ViewHolder jedes Typs. Erhöhen Sie die Größe für komplexe Layouts: recyclerView.getRecycledViewPool().setMaxRecycledViews(VIEW_TYPE_NORMAL, maxCount). Wenn ein RecyclerView mehrere View-Typen (viewType) hat, führt der Pool separate Stapel für jeden. Das Teilen eines RecycledViewPool zwischen verschiedenen RecyclerViews spart Speicher auf Bildschirmen mit verschachtelten Listen.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch