RecyclerView — Android Jetpack komponens nagy adathalmazok hatékony megjelenítéséhez listák és rácsok formájában. A ListView-val ellentétben a RecyclerView újrahasznosítja a ViewHolder-eket, és a LayoutManager-en keresztül kezeli az elrendezést. A Google (Android Developers, 2026) szerint a RecyclerView akár 60 képkockát másodpercenként feldolgoz egy 1000+ elemű lista görgetésekor a ViewHolder pool és a DiffUtil különbségalgoritmus segítségével. Az Android-alkalmazások architektúrájáról bővebben a ListView-ról szóló cikkünkben olvashat.
Főbb pontok
RecyclerView — az Android Jetpack könyvtár komponense, amelyet a Google I/O 2014-ben mutattak be az Android Support Library v7 részeként. Dinamikus listák és rácsok nagy teljesítményű megjelenítésére tervezték. A RecyclerView a ListView helyettesítőjeként jelent meg, és megoldja elődje kulcsproblémáját — a ViewHolder-ek kötelező újrahasznosításának hiányát.
A RecyclerView architektúrája a Model-View-Adapter mintára épül: az adatok a modellben (List, LiveData, Flow) tárolódnak, a megjelenítést az Adapter kezeli, az elrendezést pedig a LayoutManager vezérli. Minden komponens a saját felelősségi területéért felelős, ami rugalmassá és bővíthetővé teszi a rendszert.
Az Android Developers (2025) felmérése szerint a RecyclerView a Google Play top-100-ból 78%-ban használatos. Egy 1000+ elemű lista görgetési teljesítménye 60 FPS-en marad stabil középkategóriás eszközökön három mechanizmusnak köszönhetően: ViewHolder pool, differenciális frissítésszámítás és aszinkron adatbetöltés.
A RecyclerView a következőkhöz optimális: ismeretlen számú elemet tartalmazó listák (feed-ek, chat-ek, naplók), N oszlopos rácsok (galériák, katalógusok), kaszkád elrendezések (Pinterest táblák), elemek hozzáadásának/eltávolításának animációjával rendelkező listák. Egyszerű, 2-5 elemet tartalmazó képernyőkhöz a LinearLayout vagy a ScrollView egyszerűbb és hatékonyabb — a RecyclerView többletterhelést jelent.
A RecyclerView használatához adja hozzá a függőséget a build.gradle (app) fájlhoz: implementation 'androidx.recyclerview:recyclerview:1.4.0'. Minimális API verzió — 14 (Android 4.0). Az AndroidX RecyclerView 1.3.0-tól kezdve elérhetők a recyclerview-selection modul elemek kijelöléséhez és a recyclerview-swipe modul húzáshoz.
RecyclerView három független rétegre oszlik: az Adapter kezeli az adatokat és a ViewHolder-eket, a LayoutManager felelős az elemek pozicionálásáért, az ItemAnimator vezérli az animációkat. Ez az architektúra lehetővé teszi bármely réteg cseréjét a többi megváltoztatása nélkül — például a LinearLayoutManager-ről GridLayoutManager-re váltást az Adapter kódjának módosítása nélkül.
| Komponens | Feladatok | Megvalósítás |
|---|---|---|
| Adapter | ViewHolder-ek létrehozása, adatok kötése a View-hoz, változások jelzése | RecyclerView.Adapter<VH> |
| ViewHolder | View referenciák gyorsítótárazása, findViewById() elkerülése | RecyclerView.ViewHolder |
| LayoutManager | Elemek elhelyezése, görgetési irány meghatározása | LinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager |
| ItemAnimator | Elemek hozzáadásának, eltávolításának, mozgatásának animációja | DefaultItemAnimator |
| ItemDecoration | Elválasztók, távolságok, háttér rajzolása elemek között | RecyclerView.ItemDecoration |
Munkaciklus: (1) Az Adapter létrehozza a ViewHolder-t az onCreateViewHolder() segítségével, (2) a LayoutManager meghatározza az új View pozícióját a képernyőn, (3) az Adapter az onBindViewHolder() segítségével köti az adatokat, (4) görgetéskor a képernyőről eltűnt ViewHolder-ek a pool-ba (RecycledViewPool) kerülnek újrahasznosításra. Új View-ok létrehozása helyett a meglévők kerülnek újrahasznosításra — ez a kulcsfontosságú teljesítménymechanizmus.
ViewHolder — egy osztály, amely a lista elemen belüli View-kra (TextView, ImageView stb.) tárol referenciákat. ViewHolder nélkül minden görgetéskor a rendszer meghívná a findViewById()-t — az Android UI egyik legdrágább műveletét. A ViewHolder az első kötés után megjegyzi a referenciákat, ezzel kiküszöböli ezt a hívást.
// Adatmodell
data class Article(
title: String,
summary: String,
author: String,
imageUrl: String?
)
// ViewHolder — referenciákat tárol a View-hoz
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
}
}
Gyakorlati szabály: minden View-t az elem elrendezésében a ViewHolder tulajdonságaként kell deklarálni a findViewById() segítségével pontosan egyszer — a konstruktorban. A bind() metódus nem hívja meg a findViewById()-t, csak a szöveget, színeket és hallgatókat állítja be. Ez a megközelítés a Google (Android Performance Patterns, 2025) szerint 30-50%-kal gyorsítja a lista görgetését.
LayoutManager meghatározza, hogy az elemek hogyan helyezkednek el a RecyclerView-n belül. Alapértelmezés szerint az Android három megvalósítást kínál: LinearLayoutManager, GridLayoutManager és StaggeredGridLayoutManager. A LayoutManager választása befolyásolja a felhasználó adatészlelését és a görgetési teljesítményt.
| LayoutManager | Elhelyezés | Mikor használjuk | Beállítási módszer |
|---|---|---|---|
| LinearLayoutManager | Lista (függőleges vagy vízszintes) | Feed-ek, chat-ek, értesítések, terméklisták | LinearLayoutManager(context) |
| GridLayoutManager | N oszlopos rács | Galériák, katalógusok, ikonok, képrács | GridLayoutManager(context, spanCount) |
| StaggeredGridLayoutManager | Kaszkád rács (különböző magasságú elemek) | Pinterest táblák, jegyzetek, masonry galériák | StaggeredGridLayoutManager(spanCount, orientation) |
// LinearLayoutManager beállítása Fragment-ben
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)
// Optimalizálás: rögzített méret + pool
recyclerView.setHasFixedSize(true)
recyclerView.setItemViewCacheSize(20)
// Elválasztó elemek között
val divider = DividerItemDecoration(requireContext(), LinearLayoutManager.VERTICAL)
recyclerView.addItemDecoration(divider)
}
}
Teljesítmény: a LinearLayoutManager függőleges görgetéssel a leggyorsabb opció, mivel az elemek egymás után helyezkednek el, és a LayoutManager O(1) idő alatt számítja ki a pozíciókat. A GridLayoutManager további számításokat igényel az oszlopokra bontáshoz, de rögzített spanCount mellett hatékony marad. A StaggeredGridLayoutManager a három közül a leglassabb, mert ki kell számítania az elem pozícióját a kaszkádban a szomszédos elemek magasságának figyelembevételével. Csak akkor használja, ha vizuálisan különböző cellamagasságokra van szükség.
Adapter a RecyclerView-ban megvalósítja a GoF Adapter mintáját: az adatokat (List<T>) a képernyőn megjelenő ViewHolder-ekké alakítja. Az adatok változásakor az Adapter értesítheti a RecyclerView-t a notifyDataSetChanged(), notifyItemInserted() és hasonló metódusokon keresztül. A probléma az, hogy a notifyDataSetChanged() az összes látható elemet újrarajzolja, ami rángatózáshoz (jank) vezet.
// Adapter DiffUtil-lel a hatékony frissítéshez
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
// Lista frissítése DiffUtil segítségével
fun updateArticles(newArticles: List<Article>) {
val diffCallback = ArticleDiffCallback(articles, newArticles)
val diffResult = DiffUtil.calculateDiff(diffCallback)
articles = newArticles
diffResult.dispatchUpdatesTo(this)
}
}
// Callback a DiffUtil számára
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 az Eugene W. Myers-féle különbségalgoritmust használja, amely kiszámítja a minimális műveletszámot (insert, remove, move, change) a régi lista újra alakításához. Egy 100 elemes lista esetén a DiffUtil 1-5 ms alatt működik (Google, 2025). Nagy listákhoz (10000+) használja az AsyncListDiffer vagy a PagingDataAdapter elemet a Paging könyvtárból — ezek háttérszálon végzik a számításokat.
ListView — a RecyclerView elődje, az Android 1.0 (API 1) verzióban jelent meg. Szintén listákat jelenít meg, de nem kényszeríti ki a ViewHolder-t, nem támogatja a LayoutManager-t, és nem tudja animálni a változásokat. A RecyclerView-t a ListView helyettesítőjeként tervezték szigorúbb architektúrával és jobb teljesítménnyel.
| Kritérium | RecyclerView | ListView |
|---|---|---|
| ViewHolder | Kötelező (architektúra) | Ajánlott, de nem kötelező |
| LayoutManager | Felosztás: lista, rács, kaszkád | Csak függőleges lista |
| Változások animációja | DefaultItemAnimator rögtön | Nincs beépített támogatás |
| Változások jelzése | Pontszerű: notifyItemInserted/Removed | notifyDataSetChanged() csak teljes lista |
| DiffUtil | Támogatás DiffUtil.Callback segítségével | Nincs megfelelője |
| Elválasztók | ItemDecoration (egyéni) | android:divider (beépített) |
| Minimális verzió | API 14 (Android 4.0) AndroidX-szel | API 1 (minden verzió) |
Google ajánlása (Android Developers, 2026): használja a RecyclerView-t minden új projekthez. A ListView megtartható régi kódbázisokban (legacy), ahol a migráció nem indokolja a költségeket. A RecyclerView jobb teljesítményt nyújt 100+ elemen, támogatja a vízszintes görgetést és rácsokat további megoldások nélkül. Az Android 15-ben a ListView hivatalosan részben elavultként van megjelölve.
Gyakran Ismételt Kérdések
Ellenőrizze három feltételt: (1) Az Adapter be van állítva a recyclerView.adapter = adapter segítségével, (2) a LayoutManager be van állítva a recyclerView.layoutManager = LinearLayoutManager(context) segítségével, (3) a lista adatai nem üresek, és az adapter értesítve lett (notifyDataSetChanged()). Tipikus hiba — az adatok beállítása a notifyDataSetChanged() meghívása után. Az adatokat az értesítés előtt kell hozzárendelni. Ellenőrizze a lista méretét: az adapter.itemCount értékének nagyobbnak kell lennie 0-nál.
Lassúság görgetéskor (jank) akkor fordul elő, amikor az onBindViewHolder() nehéz műveleteket hajt végre: képek betöltése gyorsítótár nélkül, findViewById() a bind-en belül, összetett számítások. Megoldások: (1) használja a Glide vagy Coil könyvtárat aszinkron képbetöltéshez, (2) helyezze át az összes findViewById()-t a ViewHolder konstruktorába, (3) differenciális számításokhoz használja az AsyncListDiffer-t. Kapcsolja be a GPU-profilozást az Android Studio-ban (Profile GPU Rendering) a lassú képkockák megtalálásához.
Adja át az irányt a LayoutManager-nek: LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false). A második paraméter a reverseLayout (false = balról jobbra). Vízszintes rácshoz használja a GridLayoutManager elemet vízszintes iránnyal vagy egyedi LinearSnapHelper-t lapozható görgetéshez. A vízszintes listák jól alkalmasak termékkarusszelekhez, képekhez, kategóriákhoz.
RecyclerView nem rendelkezik beépített onClickListener-rel (ellentétben a ListView onItemClickListener-jével). Valósítsa meg a ViewHolder-ben: adjon át egy lambda-t a konstruktornak, és állítsa be az itemView.setOnClickListener-t. Példa: class ArticleViewHolder(itemView: View, val onItemClick: (Article) -> Unit) : RecyclerView.ViewHolder(itemView). Hívja meg az onItemClick(article)-t a bind()-en belül. Alternatíva — állítsa be a RecyclerView.addOnItemTouchListener()-t gesztusok kezeléséhez.
RecycledViewPool — a görgetés során láthatatlanná vált ViewHolder-ek belső pool-ja. A megsemmisítés helyett a pool-ban tárolódnak és újrahasznosulnak. Alapértelmezés szerint a pool típusonként 5 ViewHolder-t tárol. Növelje a méretet összetett elrendezésekhez: recyclerView.getRecycledViewPool().setMaxRecycledViews(VIEW_TYPE_NORMAL, maxCount). Ha a RecyclerView több View-típust tartalmaz (viewType), a pool mindegyikhez külön vermet tárol. A RecycledViewPool megosztása különböző RecyclerView-ok között memóriát takarít meg a beágyazott listákat tartalmazó képernyőkön.
Összegzés
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is