RecyclerView — ce este, ViewHolder și Adapter în Android

Autor: IT Sectr Publicat: 2026-02-23 Timp de citire: 8 min

RecyclerView — component Android Jetpack pentru afișarea eficientă a seturilor mari de date sub formă de liste și grile. Spre deosebire de ListView, RecyclerView reutilizează ViewHolder-i și gestionează aspectul prin LayoutManager. Conform Google (Android Developers, 2026), RecyclerView procesează până la 60 de cadre pe secundă la derularea unei liste cu 1000+ de elemente datorită pool-ului de ViewHolder-i și algoritmului DiffUtil. Citiți mai multe despre arhitectura aplicațiilor Android în articolul nostru despre ListView.

Principalele

  • RecyclerView — component modern pentru liste în Android, care a înlocuit ListView în Android 5.0 (API 21).
  • ViewHolder — model pentru stocarea în cache a referințelor către View, accelerând reutilizarea celulelor la derulare.
  • Adapter — veriga de legătură între date și RecyclerView, responsabilă pentru crearea ViewHolder-ilor și legarea datelor.
  • LayoutManager — determină aranjarea elementelor: listă verticală/orizontală (LinearLayoutManager), grilă (GridLayoutManager), cascadă (StaggeredGridLayoutManager).
  • DiffUtil — utilitar pentru calcularea diferențelor între lista veche și cea nouă, minimizând redesenarea elementelor.

Ce este RecyclerView?

RecyclerView — component al bibliotecii Android Jetpack, prezentat la Google I/O 2014 ca parte a Android Support Library v7. Este conceput pentru afișarea listelor și grilelor dinamice cu performanță ridicată. RecyclerView a apărut ca înlocuitor pentru ListView și rezolvă problema cheie a predecesorului — lipsa reutilizării forțate a ViewHolder-ilor.

Arhitectura RecyclerView este construită pe modelul Model-View-Adapter: datele sunt stocate în model (List, LiveData, Flow), afișarea este gestionată de Adapter, iar aranjamentul este controlat de LayoutManager. Fiecare component este responsabil pentru zona sa de responsabilitate, ceea ce face sistemul flexibil și extensibil.

Conform sondajului Android Developers (2025), RecyclerView este utilizat în 78% dintre aplicațiile Android din top-100 Google Play. Performanța de derulare a unei liste cu 1000+ elemente rămâne stabilă la 60 FPS pe dispozitivele de gamă medie datorită a trei mecanisme: pool-ul de ViewHolder-i, calculul diferențial al actualizărilor și încărcarea asincronă a datelor.

Când să utilizați RecyclerView

RecyclerView este optim pentru: liste cu număr necunoscut de elemente (feed-uri, chat-uri, log-uri), grile cu N coloane (galerii, cataloage), aranjamente în cascadă (panouri Pinterest), liste cu animație de adăugare/ștergere a elementelor. Pentru ecrane simple cu 2-5 elemente, LinearLayout sau ScrollView sunt mai simple și mai eficiente — RecyclerView adaugă overhead.

Configurarea dependenței

Pentru a utiliza RecyclerView, adăugați dependența în build.gradle (app): implementation 'androidx.recyclerview:recyclerview:1.4.0'. Versiunea minimă API — 14 (Android 4.0). Începând cu AndroidX RecyclerView 1.3.0, sunt disponibile modulele recyclerview-selection pentru selectarea elementelor și recyclerview-swipe pentru glisări.

Cum funcționează RecyclerView: trei componente cheie

RecyclerView este împărțit în trei straturi independente: Adapter gestionează datele și ViewHolder-ii, LayoutManager se ocupă de poziționarea elementelor, ItemAnimator controlează animațiile. O astfel de arhitectură permite înlocuirea oricărui strat fără a modifica celelalte — de exemplu, trecerea de la LinearLayoutManager la GridLayoutManager fără a schimba codul Adapter-ului.

ComponentResponsabilitățiImplementare
AdapterCrearea ViewHolder-ilor, legarea datelor de View, notificarea schimbărilorRecyclerView.Adapter<VH>
ViewHolderStocarea în cache a referințelor către View, evitarea findViewById()RecyclerView.ViewHolder
LayoutManagerAranjarea elementelor, determinarea direcției de derulareLinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager
ItemAnimatorAnimația adăugării, ștergerii, mutării elementelorDefaultItemAnimator
ItemDecorationDesenarea separatoarelor, spațiilor, fundalurilor între elementeRecyclerView.ItemDecoration

Ciclu de funcționare: (1) Adapter creează ViewHolder prin onCreateViewHolder(), (2) LayoutManager determină poziția noului View pe ecran, (3) Adapter leagă datele prin onBindViewHolder(), (4) la derulare, ViewHolder-ii care au ieșit din ecran ajung în pool (RecycledViewPool) pentru reutilizare. În loc să creeze View-uri noi, sunt reutilizate cele existente — acesta este mecanismul cheie de performanță.

Implementarea ViewHolder în RecyclerView

ViewHolder — este o clasă care stochează referințe către View (TextView, ImageView etc.) în interiorul elementului de listă. Fără ViewHolder, la fiecare derulare sistemul ar apela findViewById() — una dintre cele mai costisitoare operații din Android UI. ViewHolder elimină acest apel, memorând referințele după prima legare.

kotlin
// Model de date
data class Article(
    title: String,
    summary: String,
    author: String,
    imageUrl: String?
)

// ViewHolder — stochează referințe către View
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
    }
}

Regulă practică: fiecare View din aspectul elementului trebuie declarat ca proprietate a ViewHolder cu findViewById() exact o dată — în constructor. Metoda bind() nu apelează findViewById(), ci doar setează textul, culorile și ascultătorii. Această abordare accelerează derularea listei cu 30-50% conform Google (Android Performance Patterns, 2025).

Tipuri de LayoutManager: alegerea aranjării elementelor

LayoutManager determină modul în care elementele sunt aranjate în interiorul RecyclerView. În mod implicit, Android oferă trei implementări: LinearLayoutManager, GridLayoutManager și StaggeredGridLayoutManager. Alegerea LayoutManager influențează percepția datelor de către utilizator și performanța de derulare.

LayoutManagerAranjareCând să utilizațiMetoda de setare
LinearLayoutManagerListă (verticală sau orizontală)Feed-uri, chat-uri, notificări, liste de produseLinearLayoutManager(context)
GridLayoutManagerGrilă cu N coloaneGalerii, cataloage, pictograme, grilă de imaginiGridLayoutManager(context, spanCount)
StaggeredGridLayoutManagerGrilă în cascadă (înălțimi diferite ale elementelor)Panouri Pinterest, note, galerii masonryStaggeredGridLayoutManager(spanCount, orientation)
kotlin
// Configurarea LinearLayoutManager în Fragment
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)

        // Optimizare: dimensiune fixă + pool
        recyclerView.setHasFixedSize(true)
        recyclerView.setItemViewCacheSize(20)

        // Separator între elemente
        val divider = DividerItemDecoration(requireContext(), LinearLayoutManager.VERTICAL)
        recyclerView.addItemDecoration(divider)
    }
}

Performanță: LinearLayoutManager cu derulare verticală este cea mai rapidă opțiune, deoarece elementele sunt aranjate secvențial, iar LayoutManager calculează pozițiile în O(1). GridLayoutManager necesită calcule suplimentare pentru împărțirea pe coloane, dar rămâne eficient cu un spanCount fix. StaggeredGridLayoutManager este cel mai lent dintre cele trei, deoarece trebuie să calculeze poziția elementului în cascadă ținând cont de înălțimea elementelor vecine. Folosiți-l doar când înălțimea diferită a celulelor este necesară vizual.

Adapter și DiffUtil: actualizarea eficientă a datelor

Adapter în RecyclerView implementează modelul Adapter din GoF: transformă datele (List<T>) în ViewHolder-i afișați pe ecran. La modificarea datelor, Adapter poate notifica RecyclerView prin metodele notifyDataSetChanged(), notifyItemInserted() și similare. Problema este că notifyDataSetChanged() redesenează toate elementele vizibile, ceea ce duce la tremur (jank).

kotlin
// Adapter cu DiffUtil pentru actualizare eficientă
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

    // Actualizarea listei prin DiffUtil
    fun updateArticles(newArticles: List<Article>) {
        val diffCallback = ArticleDiffCallback(articles, newArticles)
        val diffResult = DiffUtil.calculateDiff(diffCallback)
        articles = newArticles
        diffResult.dispatchUpdatesTo(this)
    }
}

// Callback pentru 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 utilizează algoritmul Eugene W. Myers' difference algorithm, care calculează numărul minim de operații (insert, remove, move, change) pentru a transforma lista veche în cea nouă. Pentru o listă de 100 de elemente, DiffUtil funcționează în 1-5 ms (Google, 2025). Pentru liste mari (10000+), utilizați AsyncListDiffer sau PagingDataAdapter din biblioteca Paging — acestea efectuează calculele în fundal.

RecyclerView vs ListView: comparație

ListView — predecesorul RecyclerView, apărut în Android 1.0 (API 1). De asemenea, afișează liste, dar nu impune ViewHolder, nu suportă LayoutManager și nu poate anima modificările. RecyclerView a fost proiectat ca înlocuitor pentru ListView cu o arhitectură mai strictă și performanță mai bună.

CriteriuRecyclerViewListView
ViewHolderObligatoriu (arhitectură)Recomandat, dar nu obligatoriu
LayoutManagerSeparare: listă, grilă, cascadăDoar listă verticală
Animația modificărilorDefaultItemAnimator din cutieFără suport încorporat
Notificarea modificărilorPunctuale: notifyItemInserted/RemovednotifyDataSetChanged() doar întreaga listă
DiffUtilSuport prin DiffUtil.CallbackFără echivalent
SeparatoareItemDecoration (personalizate)android:divider (încorporat)
Versiune minimăAPI 14 (Android 4.0) prin AndroidXAPI 1 (toate versiunile)

Recomandarea Google (Android Developers, 2026): utilizați RecyclerView pentru toate proiectele noi. ListView poate fi păstrat în bazele de cod vechi (legacy), unde migrarea nu justifică costurile. RecyclerView oferă performanță mai bună pe 100+ elemente, suportă derulare orizontală și grile fără soluții suplimentare. În Android 15, ListView este marcat oficial ca parțial depreciat.

Întrebări frecvente

RecyclerView nu afișează elemente — ce să fac?

Verificați trei condiții: (1) Adapter setat prin recyclerView.adapter = adapter, (2) LayoutManager setat prin recyclerView.layoutManager = LinearLayoutManager(context), (3) datele din listă nu sunt goale și adapter a fost notificat (notifyDataSetChanged()). Eroarea tipică — setarea datelor după apelarea notifyDataSetChanged(). Datele trebuie atribuite înainte de notificare. Verificați dimensiunea listei: adapter.itemCount trebuie să fie mai mare decât 0.

De ce RecyclerView se derulează cu întârzieri?

Întârzierile la derulare (jank) apar când onBindViewHolder() execută operații grele: încărcarea imaginilor fără cache, findViewById() în interiorul bind, calcule complexe. Soluții: (1) utilizați biblioteca Glide sau Coil pentru încărcarea asincronă a imaginilor, (2) mutați toate findViewById() în constructorul ViewHolder, (3) pentru calcule diferențiale utilizați AsyncListDiffer. Activați profilarea GPU în Android Studio (Profile GPU Rendering) pentru a găsi cadrele lente.

Cum să fac un RecyclerView orizontal?

Transmiteți orientarea către LayoutManager: LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false). Al doilea parametru este reverseLayout (false = de la stânga la dreapta). Pentru o grilă orizontală, utilizați GridLayoutManager cu orientare orizontală sau LinearSnapHelper personalizat pentru derulare paginată. Listele orizontale sunt potrivite pentru carusele de produse, imagini, categorii.

Cum să adaug un click listener la elementul RecyclerView?

RecyclerView nu are onClickListener încorporat (spre deosebire de ListView cu onItemClickListener). Implementați-l în ViewHolder: transmiteți o lambda în constructor și setați itemView.setOnClickListener. Exemplu: class ArticleViewHolder(itemView: View, val onItemClick: (Article) -> Unit) : RecyclerView.ViewHolder(itemView). Apelați onItemClick(article) în interiorul bind(). Alternativă — setați RecyclerView.addOnItemTouchListener() pentru gestionarea gesturilor.

Ce este RecycledViewPool și cum se configurează?

RecycledViewPool — pool-ul intern de ViewHolder-i care au devenit invizibili la derulare. În loc să fie distruși, sunt păstrați în pool și reutilizați. În mod implicit, pool-ul stochează 5 ViewHolder-i de fiecare tip. Măriți dimensiunea pentru aspecte complexe: recyclerView.getRecycledViewPool().setMaxRecycledViews(VIEW_TYPE_NORMAL, maxCount). Dacă RecyclerView are mai multe tipuri de View (viewType), pool-ul stochează stive separate pentru fiecare. Partajarea RecycledViewPool între diferite RecyclerView economisește memorie în ecranele cu liste imbricate.

Rezumat

  • RecyclerView — component modern Android Jetpack pentru liste și grile cu performanță de până la 60 FPS.
  • ViewHolder — model obligatoriu pentru cache-ul View, eliminând findViewById() la fiecare derulare.
  • Adapter — gestionează datele și crearea ViewHolder-ilor prin onCreateViewHolder și onBindViewHolder.
  • LayoutManager — trei implementări: LinearLayoutManager (listă), GridLayoutManager (grilă), StaggeredGridLayoutManager (cascadă).
  • DiffUtil — algoritm pentru actualizarea minimă a listei: redesenare punctuală în loc de completă.
  • RecyclerView este utilizat în 78% dintre aplicațiile Android din top-100 și este recomandat oficial de Google în locul ListView.
  • Performanța RecyclerView se realizează prin pool-ul de ViewHolder-i, notificări punctuale și calcul diferențial asincron.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și