Sobes.tech
Middle

Ako vyriešiť problém s rôznymi typmi zobrazení pre RecyclerView?

sobes.tech AI

Odpoveď od AI

Existuje niekoľko prístupov:

  1. Použitie viacerých ViewTypes v adaptéri. Najbežnejší a najflexibilnejší spôsob. Adaptér prepíše metódu getItemViewType, ktorá vráti typ zobrazenia pre konkrétnu pozíciu. Potom sa tento typ používa v metódach onCreateViewHolder a onBindViewHolder na vytvorenie a viazanie príslušného ViewHolder.

    class MyAdapter(private val items: List<Item>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    
        private val VIEW_TYPE_TEXT = 0
        private val VIEW_TYPE_IMAGE = 1
    
        override fun getItemViewType(position: Int): Int {
            return when (items[position]) {
                is TextItem -> VIEW_TYPE_TEXT
                is ImageItem -> VIEW_TYPE_IMAGE
            }
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
            return when (viewType) {
                VIEW_TYPE_TEXT -> {
                    val view = LayoutInflater.from(parent.context).inflate(R.layout.item_text, parent, false)
                    TextViewHolder(view)
                }
                VIEW_TYPE_IMAGE -> {
                    val view = LayoutInflater.from(parent.context).inflate(R.layout.item_image, parent, false)
                    ImageViewHolder(view)
                }
                else -> throw IllegalArgumentException("Neplatný typ zobrazenia")
            }
        }
    
        override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
            when (holder.itemViewType) {
                VIEW_TYPE_TEXT -> {
                    val textHolder = holder as TextViewHolder
                    val textItem = items[position] as TextItem
                    textHolder.bind(textItem)
                }
                VIEW_TYPE_IMAGE -> {
                    val imageHolder = holder as ImageViewHolder
                    val imageItem = items[position] as ImageItem
                    imageHolder.bind(imageItem)
                }
            }
        }
    
        override fun getItemCount(): Int {
            return items.size
        }
    
        // ViewHolders pre rôzne typy
        class TextViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            private val textView: TextView = itemView.findViewById(R.id.textView)
            fun bind(item: TextItem) {
                textView.text = item.text
            }
        }
    
        class ImageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            private val imageView: ImageView = itemView.findViewById(R.id.imageView)
            fun bind(item: ImageItem) {
                // Načítanie obrázka
            }
        }
    }
    
    data class TextItem(val text: String)
    data class ImageItem(val imageUrl: String)
    
  2. Použitie knižníc. Existujú knižnice, ktoré zjednodušujú prácu s viacerými ViewTypes, napríklad Groupie alebo Epoxy. Poskytujú abstrakcie na definovanie "items" s príslušnými ViewHolders a logikou viazania.

    • Groupie:

      class MyItemAdapter(private val items: List<GroupieItem<*>>) : GroupAdapter<ViewHolder>() {
          init {
              addAll(items)
          }
      }
      
      // Príklad Groupie Item
      class TextItemGroupie(private val text: String) : Item<ViewHolder>() {
          override fun getLayout(): Int = R.layout.item_text
      
          override fun bind(viewHolder: ViewHolder, position: Int) {
              viewHolder.itemView.findViewById<TextView>(R.id.textView).text = text
          }
      }
      
      class ImageItemGroupie(private val imageUrl: String) : Item<ViewHolder>() {
          override fun getLayout(): Int = R.layout.item_image
      
          override fun bind(viewHolder: ViewHolder, position: Int) {
             // Načítanie obrázka
          }
      }
      
    • Epoxy: Používa anotácie na generovanie EpoxyModel a EpoxyController.

  3. Použitie zložených ViewHolders. Menej bežný prístup, keď jeden ViewHolder obsahuje niekoľko rôznych zobrazení a výber viditeľného zobrazenia sa vykonáva v ViewHolder (cez setVisibility alebo inými spôsobmi). Neodporúča sa pre veľké množstvo rôznych typov alebo zložitú logiku.

  4. Rozdelenie dát. Ak je možné dáta jasne rozdeliť na skupiny s rôznymi zobrazeniami, možno použiť niekoľko nezávislých RecyclerViews (čo je často neoptimalizované) alebo kompozíciu adaptér.