RecyclerView OnClickListener using interface

后端 未结 11 799
清歌不尽
清歌不尽 2020-12-01 09:49

I use RecyclerView adapter to display data inside an activity, I want to implement onClickListener inside the activity, currently, I am setting

11条回答
  •  醉话见心
    2020-12-01 09:58

    Registering clickListener inside onCreateView instead of onBindViewHolder is more performant since you only add listener when a view is created not ever time recyclerView is scrolled.

    And i use ListAdapter with DiffUtil callback instead of RecyclerViewAdapter

    abstract class BaseListAdapter(
        callBack: DiffUtil.ItemCallback = DefaultItemDiffCallback(),
        private inline val onItemClicked: ((ItemType, Int) -> Unit)? = null
    ) : ListAdapter(
        AsyncDifferConfig.Builder(callBack)
            .setBackgroundThreadExecutor(Executors.newSingleThreadExecutor())
            .build()
    ) {
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseItemViewHolder {
    
            return BaseItemViewHolder(
    
                DataBindingUtil.inflate(
                    LayoutInflater.from(parent.context),
                    getLayoutRes(viewType),
                    parent, false
                )
            ).apply {
                onViewHolderCreated(this, viewType, binding)
            }
    
        }
    
        fun createCustomViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    
            return BaseItemViewHolder(
    
                DataBindingUtil.inflate(
                    LayoutInflater.from(parent.context),
                    getLayoutRes(viewType),
                    parent, false
                )
            )
        }
    
        override fun onBindViewHolder(
            holder: BaseItemViewHolder,
            position: Int,
            payloads: MutableList
        ) {
            val item: ItemType? = currentList.getOrNull(position)
    
            item?.let {
                holder.binding.setVariable(BR.item, item)
                onViewHolderBound(holder.binding, item, position, payloads)
                holder.binding.executePendingBindings()
            }
    
        }
    
        override fun onBindViewHolder(holder: BaseItemViewHolder, position: Int) {
    
        }
    
    
        /**
         * get layout res based on view type
         */
        protected abstract fun getLayoutRes(viewType: Int): Int
    
        /**
         * Called when a ViewHolder is created. ViewHolder is either created first time or
         * when data is refreshed.
         *
         * This method is not called when RecyclerView is being scrolled
         */
        open fun onViewHolderCreated(
            viewHolder: RecyclerView.ViewHolder,
            viewType: Int,
            binding: ViewDataBinding
        ) {
    
            binding.root.setOnClickListener {
                onItemClicked?.invoke(getItem(viewHolder.bindingAdapterPosition), viewHolder.bindingAdapterPosition)
            }
        }
    
        /**
         * bind view while RecyclerView is being scrolled and new items are bound
         */
        open fun onViewHolderBound(
            binding: ViewDataBinding,
            item: ItemType,
            position: Int,
            payloads: MutableList
        ) {
    
        }
    
    
    }
    
    open class BaseItemViewHolder(
        val binding: ViewDataBinding
    ) : RecyclerView.ViewHolder(binding.root)
    
    
    class DefaultItemDiffCallback : DiffUtil.ItemCallback() {
    
        override fun areItemsTheSame(
            oldItem: ItemType,
            newItem: ItemType
        ): Boolean {
            return oldItem === newItem
        }
    
        override fun areContentsTheSame(
            oldItem: ItemType,
            newItem: ItemType
        ): Boolean {
            return oldItem.hashCode() == newItem.hashCode()
        }
    }
    

    Another better user experience is using onBindViewHolder with payLoad which lets you only update some part of the rows instead of whole row. For instance you have image, title and body in rows, and only body changes frequently, without payload image flashes and provides bad user experience. But with payload you can decide which part of the row should be updated allowing you not to reload parts that were not updated.

提交回复
热议问题