рд╕рд╛рдорд╛рдиреНрдп рдкреБрдирд░реНрдирд╡реАрдиреАрдХрд░рдг рджреЗрдЦреЗрдВ рдпрд╛ рдмреЙрдпрд▓рд░рдкреНрд▓реЗрдЯ рдХреЛрдб рдХреИрд╕реЗ рдирд╣реАрдВ рд▓рд┐рдЦреЗрдВ

рд╣рдо рд╕рднреА рдЖрд╡реЗрджрди рд▓рд┐рдЦрддреЗ рд╣реИрдВ рдФрд░ рд╣рдо рд╕рднреА рдХреА рд╕реВрдЪреА рд╣реИред рдФрд░ рд╕рдмрд╕реЗ рд╕реНрдкрд╖реНрдЯ рд╕рдорд╛рдзрд╛рди RecyclerView рд╣реИред рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╕реНрд╡рдпрдВ рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рд╣реИ рдФрд░ RecyclerView рдкрд░ рдПрдХ рдЧрд╛рдЗрдб рд▓рд┐рдЦрдирд╛ рдЕрдм рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдирд╣реАрдВ рд╣реИред рд▓реЗрдХрд┐рди рдПрдХ рдмрд╛рдд рд╣реИред рд╣рд░ рдмрд╛рд░ рдЬрдм рд╣рдореЗрдВ рдПрдХ рд╕реВрдЪреА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рд╣рдо рдПрдХ рд╡рд░реНрдЧ рдмрдирд╛рддреЗ рд╣реИрдВ, рдЙрд╕рдореЗрдВ рдЯреЗрдореНрдкрд▓реЗрдЯ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рдЯреЗрдореНрдкрд▓реЗрдЯ рдХрдХреНрд╖рд╛рдПрдВ рдмрдирд╛рддреЗ рд╣реИрдВред рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ 2-3 рд╕реВрдЪрд┐рдпрд╛рдВ рд╣реИрдВ, рддреЛ рдЗрд╕рдореЗрдВ рдХреБрдЫ рднреА рдЧрд▓рдд рдирд╣реАрдВ рд╣реИред рд▓реЗрдХрд┐рди рдЬрдм рдЙрдирдореЗрдВ рд╕реЗ 10 рдпрд╛ рдЙрд╕рд╕реЗ рдЕрдзрд┐рдХ рд╣реИрдВ, рддреЛ рдЖрдк рдРрд╕рд╛ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред

рдФрд░ рдПрдХ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рд╛, рдореИрдВрдиреЗ рдЦреЛрдЬрдирд╛ рд╢реБрд░реВ рдХрд┐рдпрд╛ред рдХреЛрдЯрд▓рд┐рди рдкрд░ рдПрдХ рдмрд╣реБрдд рд╣реА рджрд┐рд▓рдЪрд╕реНрдк рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдорд┐рд▓рд╛ред рдореБрдЭреЗ рдпрд╣ рдкрд╕рдВрдж рдЖрдпрд╛, рд▓реЗрдХрд┐рди рдЗрд╕рдореЗрдВ рдХреБрдЫ рддрддреНрд╡реЛрдВ рдХреА рдХрдореА рдереАред рдХреБрдЫ рдШрдВрдЯреЗ рдмрд┐рддрд╛рдиреЗ рдХреЗ рдмрд╛рдж, рдореИрдВ рдЗрд╕реЗ рдЕрдВрддрд┐рдо рд░реВрдк рджреЗрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдерд╛ рдФрд░ рдЕрдм рдПрдбреЗрдкреНрдЯрд░ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдХрдИ рд▓рд╛рдЗрдиреЗрдВ рд▓рдЧрддреА рд╣реИрдВред рдФрд░ рдпрд╣рд╛рдБ рдореИрдВ рдЗрд╕реЗ рдЖрдкрдХреЗ рд╕рд╛рде рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред

рдкрд╣рд▓реА рдЪреАрдЬ рдЬреЛ рд╣рдореЗрдВ рдХрд░рдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рд╣реИ рд╡рд╣ рд╣реИ рдПрдХ рдПрдбреЗрдкреНрдЯрд░ред

abstract class GenericAdapter<T> : RecyclerView.Adapter<RecyclerView.ViewHolder> { private var itemList = mutableListOf<T>() constructor() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return getViewHolder( LayoutInflater.from(parent.context) .inflate(viewType, parent, false) , viewType ) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { (holder as Binder<T>).bind(itemList[position], itemClickListener) } override fun getItemCount(): Int = itemList.size override fun getItemViewType(position: Int): Int = getLayoutId(position, itemList[position]) fun update(items: List<T>) { itemList = items.toMutableList() notifyDataSetChanged() } protected abstract fun getLayoutId(position: Int, obj: T): Int protected open fun getViewHolder(view: View, viewType: Int): RecyclerView.ViewHolder { return ViewHolderFactory.create(view, viewType) } internal interface Binder<T> { fun bind(data: T) } } 

рдпрд╣рд╛рдБ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИ? рд╣рдо рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░ рдПрдбреЗрдкреНрдЯрд░ рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдЙрд╕рдореЗрдВ рдореВрд▓ рдЯреЗрдореНрдкрд▓реЗрдЯ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░ рдмрд╛рдЗрдВрдбрд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬрд┐рд╕реЗ рд╣рдорд╛рд░реЗ ViewHolder рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЕрдореВрд░реНрдд getLayoutId () рд╡рд┐рдзрд┐ рдореЗрдВ, рд╣рдо рдЕрдкрдирд╛ рд▓реЗрдЖрдЙрдЯ рд╕реЗрдЯ рдХрд░реЗрдВрдЧреЗред

рд╣рдо рдЕрдкрдиреЗ ViewHolder рдХреЗ рд▓рд┐рдП рдПрдХ рдлреИрдХреНрдЯреНрд░реА рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рджред

 object ViewHolderFactory { fun create(view: View, viewType: Int): RecyclerView.ViewHolder { return when (viewType) { R.layout.item_data -> DataViewHolder(view) R.layout.item_other_data -> OtherDataViewHolder(view) else -> throw Exception("Wrong view type") } } class DataViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), GenericAdapter.Binder<Data> { override fun bind(data: Data) { itemView.apply { dateTextView.text = data.dateTitle } } class OtherDataViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), GenericAdapter.Binder<OtherData> { override fun bind(data: OtherData) { itemView.apply { dateTextView.text = data.dateTitle } } } 

рдФрд░ рдпрд╣ рд╣реИ рдХрд┐ рдЗрд╕ рдПрдбреЙрдкреНрдЯрд░ рдХреЗ рдЯреБрдХрдбрд╝реЗ рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреИрд╕реЗ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛ред

 private lateinit var adapter GenericAdapter<Data> protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); adapter = dataAdapter } private val dataAdapter = object : GenericAdapter<Data>() { override fun getLayoutId(position: Int, obj: Data): Int = R.layout.item_data } 

рд╕рдм рдХреБрдЫ рд╢рд╛рдВрдд, рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ, рддреЗрдЬ рд╣реИред рд▓рдЧрднрдЧ рдЗрд╕реА рд░реВрдк рдореЗрдВ, рдореИрдВрдиреЗ рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ред рд▓реЗрдХрд┐рди рдлрд┐рд░ рдореИрдВрдиреЗ рд╕реЛрдЪрд╛, рдХреНрд▓рд┐рдХ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рддрддреНрд╡реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛ред рдФрд░ рдпрд╣рд╛рдБ рдореЗрд░рд╛ рдирд┐рд░реНрдгрдп рд╣реИред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрдирд╛рдПрдБ

 interface OnItemClickListener<T> { fun onClickItem(data: T) } 

рдФрд░ рдЗрд╕реЗ рд╣рдорд╛рд░реЗ рдмрд╛рдЗрдВрдбрд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ рдкрд╛рд╕ рдХрд░реЗрдВ
 internal interface Binder<T> { fun bind(data: T, listener: OnItemClickListener<T>?) } 

рдФрд░ рдПрдбреЙрдкреНрдЯрд░ рдореЗрдВ, рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдирд┐рд░реНрдорд╛рддрд╛ рдмрдирд╛рдПрдБ:

  private var itemClickListener: OnItemClickListener<T>? = null constructor(listener: OnItemClickListener<T>) { itemClickListener = listener } class DataViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), GenericAdapter.Binder<Data> { override fun bind(data: Data, listener: OnItemClickListener<Data>?) { itemView.apply { dateTextView.text = data.dateTitle setOnClickListener { listener?.onClickItem(data) } } } 

рдЕрдВрдд рдореЗрдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреНрдпрд╛ рд╣реИ, рдПрдХ рдПрдбрд╛рдкреНрдЯрд░ рдЬреЛ 3 рд▓рд╛рдЗрдиреЛрдВ рдореЗрдВ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рддрддреНрд╡реЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╣реИред рдЕрдЧрд░ рд╣рдореЗрдВ рдХреНрд▓рд┐рдХреЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рддреЛ рд╣рдо рдмрд╕ рд╢реНрд░реЛрддрд╛ рдХреЛ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЗ рдкрд╛рд╕ рдирд╣реАрдВ рднреЗрдЬреЗрдВрдЧреЗред рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдм рдирд╣реАрдВ рд╣реИред

рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рд╣рдо рдЕрдкрдиреЗ рдПрдбреЗрдкреНрдЯрд░ рдореЗрдВ DiffUtils.Callback рдмрд╛рдБрдзрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред

 class GenericDiffUtil<T>( private val oldItems: List<T>, private val newItems: List<T>, private val itemDiff: GenericItemDiff<T> ) : DiffUtil.Callback() { override fun getOldListSize() = oldItems.size override fun getNewListSize() = newItems.size override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) = itemDiff.isSame(oldItems, newItems, oldItemPosition, newItemPosition) override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) = itemDiff.isSameContent(oldItems, newItems, oldItemPosition, newItemPosition) } interface GenericItemDiff<T> { fun isSame( oldItems: List<T>, newItems: List<T>, oldItemPosition: Int, newItemPosition: Int ): Boolean fun isSameContent( oldItems: List<T>, newItems: List<T>, oldItemPosition: Int, newItemPosition: Int ): Boolean } 

рдпрд╣ рд╣рдорд╛рд░реЗ рдбрд┐рдлреНрдпреВрдЯрд▓ рдХреЗ рд▓рд┐рдП рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рдЬреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдПрдбреЗрдкреНрдЯрд░ рдореЗрдВ рдПрдХ рд╡рд┐рдзрд┐ рдЬреЛрдбрд╝реЗрдВ

 private var diffUtil: GenericItemDiff<T>? = null fun setDiffUtilCallback(diffUtilImpl: GenericItemDiff<T>) { diffUtil = diffUtilImpl } 

рдФрд░ рдПрдбреЙрдкреНрдЯрд░ рдореЗрдердб рдЕрдкрдбреЗрдЯ рдХреЛ рдереЛрдбрд╝рд╛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░реЗрдВ ()
  fun update(items: List<T>) { if (diffUtil != null) { val result = DiffUtil.calculateDiff(GenericDiffUtil(itemList, items, diffUtil!!)) itemList.clear() itemList.addAll(items) result.dispatchUpdatesTo(this) } else { itemList = items.toMutableList() notifyDataSetChanged() } } 

рдФрд░ рдЗрд╕рд▓рд┐рдП рд╣рдо рдЕрдкрдиреЗ рдбрд┐рдлреНрдпреВрдЯрд▓ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ
 adapter.setDiffUtilCallback(dataDiffUtil) private val dataDiffUtil = object : GenericItemDiff<Data> { override fun isSame( oldItems: List<Data>, newItems: List<Data>, oldItemPosition: Int, newItemPosition: Int ): Boolean { val oldData = oldItems[oldItemPosition] val newData = newItems[newItemPosition] return oldData.id == newData.id } override fun isSameContent( oldItems: List<Data>, newItems: List<Data>, oldItemPosition: Int, newItemPosition: Int ): Boolean { val oldData = oldItems[oldItemPosition] val newData = newItems[newItemPosition] return oldData.name == newData.name && oldData.content == newData.content } 

рдирддреАрдЬрддрди, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛрдб рдХрд╛ рдПрдХ рд╕рд░рд▓ рдФрд░ рдХрд╛рдлреА рд▓рдЪреАрд▓рд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИред рдХрдИ ViewHolders рдХреЗ рд╕рд╛рде рдПрдбреЗрдкреНрдЯрд░ рдХреЗ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдиред рдПрдХ рдЬрдЧрд╣ рдХреЗрдВрджреНрд░реАрдХреГрдд рддрд░реНрдХред

рдпрд╣рд╛рдВ рдЖрдк рд╕реЛрд░реНрд╕ рдХреЛрдб рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ ред

рдФрд░ рдпрд╣рд╛рдВ рдЖрдк рдореВрд▓ рд╕рдВрд╕реНрдХрд░рдг рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ ред

Source: https://habr.com/ru/post/hi469557/


All Articles