Sobes.tech
Middle

Kaip išspręsti problemą su skirtingų tipų rodiniais RecyclerView?

sobes.tech AI

Atsakymas iš AI

Yra keletas požiūrių:

  1. Naudoti kelis ViewTypes adapteryje. Tai yra dažniausias ir lankstesnis būdas. Adapteris perrašys metodą getItemViewType, kuris grąžins konkrečios pozicijos vaizdo tipą. Tada šis tipas naudojamas onCreateViewHolder ir onBindViewHolder metoduose, norint sukurti ir susieti atitinkamą 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("Neteisingas vaizdo tipas")
            }
        }
    
        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
        }
    
        // Skirtingų tipų ViewHolders
        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) {
                // Vaizdo įkėlimas
            }
        }
    }
    
    data class TextItem(val text: String)
    data class ImageItem(val imageUrl: String)
    
  2. Naudoti bibliotekas. Yra bibliotekų, kurios palengvina darbą su keliomis ViewTypes, pavyzdžiui, Groupie arba Epoxy. Jos teikia abstrakcijas items su atitinkamais ViewHolders ir duoda ryšio logiką.

    • Groupie:

      class MyItemAdapter(private val items: List<GroupieItem<*>>) : GroupAdapter<ViewHolder>() {
          init {
              addAll(items)
          }
      }
      
      // Pavyzdys 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) {
             // Vaizdo įkėlimas
          }
      }
      
    • Epoxy: Naudoja anotacijas EpoxyModel ir EpoxyController generavimui.

  3. Naudoti sudėtinius ViewHolders. Mažiau paplitęs požiūris, kai vienas ViewHolder turi kelis skirtingus vaizdus ir pasirinkimas atliekamas ViewHolder viduje (per setVisibility ar kitais būdais). Nerekomenduojama daug skirtingų tipų ar sudėtingos logikos atvejais.

  4. Duomenų skirstymas. Jei duomenis galima aiškiai suskirstyti į grupes su skirtingais vaizdais, galima naudoti kelis nepriklausomus RecyclerViews (kas dažnai nėra optimalu) arba komponentuoti adapterius.