RecyclerView — τι είναι, ViewHolder και Adapter στο Android

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-02-23 Χρόνος ανάγνωσης: 8 λεπ

RecyclerView — στοιχείο Android Jetpack για αποδοτική εμφάνιση μεγάλων συνόλων δεδομένων σε μορφή λιστών και πλεγμάτων. Σε αντίθεση με το ListView, το RecyclerView επαναχρησιμοποιεί ViewHolder και διαχειρίζεται τη διάταξη μέσω LayoutManager. Σύμφωνα με την Google (Android Developers, 2026), το RecyclerView επεξεργάζεται έως 60 καρέ ανά δευτερόλεπτο κατά την κύλιση λίστας με 1000+ στοιχεία χάρη στην ομάδα ViewHolder και τον αλγόριθμο διαφοράς DiffUtil. Διαβάστε περισσότερα για την αρχιτεκτονική εφαρμογών Android στο άρθρο μας για το ListView.

Κύρια

  • RecyclerView — σύγχρονο στοιχείο για λίστες στο Android, που αντικατέστησε το ListView στο Android 5.0 (API 21).
  • ViewHolder — πρότυπο για προσωρινή αποθήκευση αναφορών σε View, επιταχύνοντας την επαναχρησιμοποίηση κελιών κατά την κύλιση.
  • Adapter — σύνδεσμος μεταξύ δεδομένων και RecyclerView, υπεύθυνος για τη δημιουργία ViewHolder και τη σύνδεση δεδομένων.
  • LayoutManager — καθορίζει τη διάταξη των στοιχείων: κάθετη/οριζόντια λίστα (LinearLayoutManager), πλέγμα (GridLayoutManager), καταρράκτης (StaggeredGridLayoutManager).
  • DiffUtil — βοηθητικό πρόγραμμα για τον υπολογισμό της διαφοράς μεταξύ παλιάς και νέας λίστας, ελαχιστοποιώντας την εκ νέου σχεδίαση στοιχείων.

Τι είναι το RecyclerView;

RecyclerView — στοιχείο της βιβλιοθήκης Android Jetpack, που παρουσιάστηκε στο Google I/O 2014 ως μέρος του Android Support Library v7. Είναι σχεδιασμένο για την εμφάνιση δυναμικών λιστών και πλεγμάτων με υψηλή απόδοση. Το RecyclerView εμφανίστηκε ως αντικατάσταση του ListView και λύνει το βασικό πρόβλημα του προκατόχου του — την έλλειψη υποχρεωτικής επαναχρησιμοποίησης ViewHolder.

Η αρχιτεκτονική του RecyclerView βασίζεται στο πρότυπο Model-View-Adapter: τα δεδομένα αποθηκεύονται στο μοντέλο (List, LiveData, Flow), η εμφάνιση διαχειρίζεται από τον Adapter και τη διάταξη ελέγχει ο LayoutManager. Κάθε στοιχείο είναι υπεύθυνο για τον τομέα ευθύνης του, καθιστώντας το σύστημα ευέλικτο και επεκτάσιμο.

Σύμφωνα με έρευνα των Android Developers (2025), το RecyclerView χρησιμοποιείται στο 78% των εφαρμογών Android από τα top-100 του Google Play. Η απόδοση κύλισης λίστας με 1000+ στοιχεία παραμένει σταθερή στα 60 FPS σε συσκευές μεσαίας κατηγορίας χάρη σε τρεις μηχανισμούς: ομάδα ViewHolder, διαφορικός υπολογισμός ενημερώσεων και ασύγχρονη φόρτωση δεδομένων.

Πότε να χρησιμοποιείτε το RecyclerView

Το RecyclerView είναι βέλτιστο για: λίστες με άγνωστο αριθμό στοιχείων (ροές, συνομιλίες, αρχεία καταγραφής), πλέγματα με N στήλες (γκαλερί, κατάλογοι), διατάξεις καταρράκτη (πίνακες Pinterest), λίστες με κινούμενα σχέδια προσθήκης/αφαίρεσης στοιχείων. Για απλές οθόνες με 2-5 στοιχεία, τα LinearLayout ή ScrollView είναι απλούστερα και αποδοτικότερα — το RecyclerView προσθέτει επιβάρυνση.

Ρύθμιση εξάρτησης

Για να χρησιμοποιήσετε το RecyclerView, προσθέστε την εξάρτηση στο build.gradle (app): implementation 'androidx.recyclerview:recyclerview:1.4.0'. Ελάχιστη έκδοση API — 14 (Android 4.0). Από το AndroidX RecyclerView 1.3.0, διατίθενται οι μονάδες recyclerview-selection για επιλογή στοιχείων και recyclerview-swipe για σάρωση.

Πώς λειτουργεί το RecyclerView: τρία βασικά στοιχεία

RecyclerView χωρίζεται σε τρία ανεξάρτητα επίπεδα: ο Adapter διαχειρίζεται δεδομένα και ViewHolder, ο LayoutManager είναι υπεύθυνος για την τοποθέτηση στοιχείων, ο ItemAnimator ελέγχει τα κινούμενα σχέδια. Αυτή η αρχιτεκτονική επιτρέπει την αντικατάσταση οποιουδήποτε επιπέδου χωρίς αλλαγή των άλλων — για παράδειγμα, μετάβαση από LinearLayoutManager σε GridLayoutManager χωρίς αλλαγή του κώδικα Adapter.

ΣτοιχείοΑρμοδιότητεςΥλοποίηση
AdapterΔημιουργία ViewHolder, σύνδεση δεδομένων με View, ειδοποίηση αλλαγώνRecyclerView.Adapter<VH>
ViewHolderΠροσωρινή αποθήκευση αναφορών σε View, αποφυγή findViewById()RecyclerView.ViewHolder
LayoutManagerΤοποθέτηση στοιχείων, καθορισμός κατεύθυνσης κύλισηςLinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager
ItemAnimatorΚινούμενα σχέδια προσθήκης, αφαίρεσης, μετακίνησης στοιχείωνDefaultItemAnimator
ItemDecorationΣχεδίαση διαχωριστικών, διαστημάτων, φόντων μεταξύ στοιχείωνRecyclerView.ItemDecoration

Κύκλος λειτουργίας: (1) Ο Adapter δημιουργεί ViewHolder μέσω onCreateViewHolder(), (2) ο LayoutManager καθορίζει τη θέση του νέου View στην οθόνη, (3) ο Adapter συνδέει δεδομένα μέσω onBindViewHolder(), (4) κατά την κύλιση, τα ViewHolder που βγήκαν από την οθόνη πηγαίνουν στην ομάδα (RecycledViewPool) για επαναχρησιμοποίηση. Αντί να δημιουργούνται νέα View, επαναχρησιμοποιούνται υπάρχοντα — αυτός είναι ο βασικός μηχανισμός απόδοσης.

Υλοποίηση ViewHolder στο RecyclerView

ViewHolder — μια κλάση που αποθηκεύει αναφορές σε View (TextView, ImageView κ.λπ.) μέσα στο στοιχείο λίστας. Χωρίς ViewHolder, σε κάθε κύλιση το σύστημα θα καλούσε findViewById() — μία από τις πιο ακριβές λειτουργίες του Android UI. Το ViewHolder εξαλείφει αυτήν την κλήση αποθηκεύοντας τις αναφορές μετά την πρώτη σύνδεση.

kotlin
// Μοντέλο δεδομένων
data class Article(
    title: String,
    summary: String,
    author: String,
    imageUrl: String?
)

// ViewHolder — αποθηκεύει αναφορές σε 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
    }
}

Πρακτικός κανόνας: κάθε View στη διάταξη του στοιχείου πρέπει να δηλώνεται ως ιδιότητα του ViewHolder με findViewById() ακριβώς μία φορά — στον κατασκευαστή. Η μέθοδος bind() δεν καλεί findViewById(), αλλά μόνο ορίζει κείμενο, χρώματα και ακροατές. Αυτή η προσέγγιση επιταχύνει την κύλιση της λίστας κατά 30-50% σύμφωνα με την Google (Android Performance Patterns, 2025).

Τύποι LayoutManager: επιλογή διάταξης στοιχείων

LayoutManager καθορίζει πώς τοποθετούνται τα στοιχεία μέσα στο RecyclerView. Από προεπιλογή, το Android προσφέρει τρεις υλοποιήσεις: LinearLayoutManager, GridLayoutManager και StaggeredGridLayoutManager. Η επιλογή LayoutManager επηρεάζει την αντίληψη των δεδομένων από τον χρήστη και την απόδοση κύλισης.

LayoutManagerΔιάταξηΠότε να χρησιμοποιείταιΜέθοδος ρύθμισης
LinearLayoutManagerΛίστα (κάθετη ή οριζόντια)Ροές, συνομιλίες, ειδοποιήσεις, λίστες προϊόντωνLinearLayoutManager(context)
GridLayoutManagerΠλέγμα με N στήλεςΓκαλερί, κατάλογοι, εικονίδια, πλέγμα εικόνωνGridLayoutManager(context, spanCount)
StaggeredGridLayoutManagerΠλέγμα καταρράκτη (διαφορετικό ύψος στοιχείων)Πίνακες Pinterest, σημειώσεις, γκαλερί masonryStaggeredGridLayoutManager(spanCount, orientation)
kotlin
// Ρύθμιση LinearLayoutManager στο 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)

        // Βελτιστοποίηση: σταθερό μέγεθος + ομάδα
        recyclerView.setHasFixedSize(true)
        recyclerView.setItemViewCacheSize(20)

        // Διαχωριστικό μεταξύ στοιχείων
        val divider = DividerItemDecoration(requireContext(), LinearLayoutManager.VERTICAL)
        recyclerView.addItemDecoration(divider)
    }
}

Απόδοση: Το LinearLayoutManager με κάθετη κύλιση είναι η ταχύτερη επιλογή, καθώς τα στοιχεία τοποθετούνται διαδοχικά και ο LayoutManager υπολογίζει θέσεις σε O(1). Το GridLayoutManager απαιτεί πρόσθετους υπολογισμούς για διαίρεση σε στήλες, αλλά παραμένει αποδοτικό με σταθερό spanCount. Το StaggeredGridLayoutManager είναι το πιο αργό από τα τρία, επειδή πρέπει να υπολογίζει τη θέση του στοιχείου στον καταρράκτη λαμβάνοντας υπόψη το ύψος γειτονικών στοιχείων. Χρησιμοποιήστε το μόνο όταν απαιτείται οπτικά διαφορετικό ύψος κελιών.

Adapter και DiffUtil: αποδοτική ενημέρωση δεδομένων

Adapter στο RecyclerView υλοποιεί το πρότυπο Adapter από GoF: μετατρέπει δεδομένα (List<T>) σε ViewHolder που εμφανίζονται στην οθόνη. Κατά την αλλαγή δεδομένων, ο Adapter μπορεί να ειδοποιήσει το RecyclerView μέσω μεθόδων notifyDataSetChanged(), notifyItemInserted() και παρόμοιων. Το πρόβλημα είναι ότι το notifyDataSetChanged() επανασχεδιάζει όλα τα ορατά στοιχεία, οδηγώντας σε τραυλισμό (jank).

kotlin
// Adapter με DiffUtil για αποδοτική ενημέρωση
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

    // Ενημέρωση λίστας μέσω DiffUtil
    fun updateArticles(newArticles: List<Article>) {
        val diffCallback = ArticleDiffCallback(articles, newArticles)
        val diffResult = DiffUtil.calculateDiff(diffCallback)
        articles = newArticles
        diffResult.dispatchUpdatesTo(this)
    }
}

// Callback για 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 χρησιμοποιεί τον αλγόριθμο διαφοράς Eugene W. Myers, ο οποίος υπολογίζει τον ελάχιστο αριθμό λειτουργιών (insert, remove, move, change) για τη μετατροπή της παλιάς λίστας σε νέα. Για λίστα 100 στοιχείων, το DiffUtil λειτουργεί σε 1-5 ms (Google, 2025). Για μεγάλες λίστες (10000+), χρησιμοποιήστε AsyncListDiffer ή PagingDataAdapter από τη βιβλιοθήκη Paging — εκτελούν υπολογισμούς στο παρασκήνιο.

RecyclerView vs ListView: σύγκριση

ListView — προκάτοχος του RecyclerView, εμφανίστηκε στο Android 1.0 (API 1). Εμφανίζει επίσης λίστες, αλλά δεν επιβάλλει ViewHolder, δεν υποστηρίζει LayoutManager και δεν μπορεί να δημιουργήσει κινούμενα σχέδια αλλαγών. Το RecyclerView σχεδιάστηκε ως αντικατάσταση του ListView με αυστηρότερη αρχιτεκτονική και καλύτερη απόδοση.

ΚριτήριοRecyclerViewListView
ViewHolderΥποχρεωτικό (αρχιτεκτονική)Συνιστάται, αλλά όχι υποχρεωτικό
LayoutManagerΔιαχωρισμός: λίστα, πλέγμα, καταρράκτηςΜόνο κάθετη λίστα
Κινούμενα σχέδια αλλαγώνDefaultItemAnimator αμέσωςΚαμία ενσωματωμένη υποστήριξη
Ειδοποίηση αλλαγώνΣημειακή: notifyItemInserted/RemovednotifyDataSetChanged() μόνο ολόκληρη λίστα
DiffUtilΥποστήριξη μέσω DiffUtil.CallbackΚανένα αντίστοιχο
ΔιαχωριστικάItemDecoration (προσαρμοσμένα)android:divider (ενσωματωμένο)
Ελάχιστη έκδοσηAPI 14 (Android 4.0) μέσω AndroidXAPI 1 (όλες οι εκδόσεις)

Σύσταση Google (Android Developers, 2026): χρησιμοποιήστε RecyclerView για όλα τα νέα έργα. Το ListView μπορεί να διατηρηθεί σε παλιές βάσεις κώδικα (legacy) όπου η μετεγκατάσταση δεν δικαιολογεί το κόστος. Το RecyclerView προσφέρει καλύτερη απόδοση σε 100+ στοιχεία, υποστηρίζει οριζόντια κύλιση και πλέγματα χωρίς πρόσθετες λύσεις. Στο Android 15, το ListView έχει επίσημα χαρακτηριστεί ως μερικώς παρωχημένο.

Συχνές Ερωτήσεις

Το RecyclerView δεν εμφανίζει στοιχεία — τι να κάνω;

Ελέγξτε τρεις συνθήκες: (1) Ο Adapter έχει οριστεί μέσω recyclerView.adapter = adapter, (2) ο LayoutManager έχει οριστεί μέσω recyclerView.layoutManager = LinearLayoutManager(context), (3) τα δεδομένα στη λίστα δεν είναι κενά και ο adapter έχει ειδοποιηθεί (notifyDataSetChanged()). Τυπικό λάθος — ορισμός δεδομένων μετά την κλήση notifyDataSetChanged(). Τα δεδομένα πρέπει να εκχωρηθούν πριν από την ειδοποίηση. Ελέγξτε το μέγεθος της λίστας: το adapter.itemCount πρέπει να είναι μεγαλύτερο από 0.

Γιατί το RecyclerView κάνει αργή κύλιση;

Καθυστερήσεις κατά την κύλιση (jank) προκύπτουν όταν το onBindViewHolder() εκτελεί βαριές λειτουργίες: φόρτωση εικόνων χωρίς προσωρινή αποθήκευση, findViewById() μέσα στο bind, σύνθετους υπολογισμούς. Λύσεις: (1) χρησιμοποιήστε τη βιβλιοθήκη Glide ή Coil για ασύγχρονη φόρτωση εικόνων, (2) μεταφέρετε όλα τα findViewById() στον κατασκευαστή ViewHolder, (3) για διαφορικούς υπολογισμούς χρησιμοποιήστε AsyncListDiffer. Ενεργοποιήστε την προφίλ GPU στο Android Studio (Profile GPU Rendering) για να βρείτε αργά καρέ.

Πώς να φτιάξω οριζόντιο RecyclerView;

Δώστε προσανατολισμό στο LayoutManager: LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false). Η δεύτερη παράμετρος είναι reverseLayout (false = αριστερά προς δεξιά). Για οριζόντιο πλέγμα, χρησιμοποιήστε GridLayoutManager με οριζόντιο προσανατολισμό ή προσαρμοσμένο LinearSnapHelper για σελιδοποίηση. Οι οριζόντιες λίστες είναι κατάλληλες για καρουζέλ προϊόντων, εικόνων, κατηγοριών.

Πώς να προσθέσω click listener στο στοιχείο RecyclerView;

RecyclerView δεν έχει ενσωματωμένο onClickListener (σε αντίθεση με το ListView με onItemClickListener). Υλοποιήστε το στο ViewHolder: δώστε ένα lambda στον κατασκευαστή και ορίστε itemView.setOnClickListener. Παράδειγμα: class ArticleViewHolder(itemView: View, val onItemClick: (Article) -> Unit) : RecyclerView.ViewHolder(itemView). Καλέστε onItemClick(article) μέσα στο bind(). Εναλλακτικά — ορίστε RecyclerView.addOnItemTouchListener() για χειρισμό χειρονομιών.

Τι είναι το RecycledViewPool και πώς να το ρυθμίσω;

RecycledViewPool — η εσωτερική ομάδα ViewHolder που έχουν γίνει αόρατα κατά την κύλιση. Αντί να καταστρέφονται, αποθηκεύονται στην ομάδα και επαναχρησιμοποιούνται. Από προεπιλογή, η ομάδα αποθηκεύει 5 ViewHolder κάθε τύπου. Αυξήστε το μέγεθος για σύνθετες διατάξεις: recyclerView.getRecycledViewPool().setMaxRecycledViews(VIEW_TYPE_NORMAL, maxCount). Εάν το RecyclerView έχει πολλούς τύπους View (viewType), η ομάδα αποθηκεύει ξεχωριστές στοίβες για τον καθένα. Η κοινή χρήση RecycledViewPool μεταξύ διαφορετικών RecyclerView εξοικονομεί μνήμη σε οθόνες με ένθετες λίστες.

Περίληψη

  • RecyclerView — σύγχρονο στοιχείο Android Jetpack για λίστες και πλέγματα με απόδοση έως 60 FPS.
  • ViewHolder — υποχρεωτικό πρότυπο για προσωρινή αποθήκευση View, εξαλείφει το findViewById() σε κάθε κύλιση.
  • Adapter — διαχειρίζεται δεδομένα και δημιουργία ViewHolder μέσω onCreateViewHolder και onBindViewHolder.
  • LayoutManager — τρεις υλοποιήσεις: LinearLayoutManager (λίστα), GridLayoutManager (πλέγμα), StaggeredGridLayoutManager (καταρράκτης).
  • DiffUtil — αλγόριθμος για ελάχιστη ενημέρωση λίστας: σημειακή επανασχεδίαση αντί πλήρους.
  • Το RecyclerView χρησιμοποιείται στο 78% των εφαρμογών Android από τα top-100 και συνιστάται επίσημα από την Google αντί του ListView.
  • Η απόδοση του RecyclerView επιτυγχάνεται μέσω ομάδας ViewHolder, σημειακών ειδοποιήσεων και ασύγχρονου διαφορικού υπολογισμού.

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης