class GeneralRecyclerView( private val diffCallback: DiffCallback, @LayoutRes private val holderResId: Int, @IdRes private val specificResViewId: Int? = null, private val onBind: (T, View) -> Unit, private val itemListener: (T, pos: Int, View) -> Unit = { _, _, _ -> kotlin.run {} }, private val specificViewListener: (T, pos: Int, View) -> Unit = { _, _, _ -> kotlin.run {} } ) : RecyclerView.Adapter>() { private val data = mutableListOf() override fun onCreateViewHolder(container: ViewGroup, position: Int): ViewHolder { val layoutInflater = LayoutInflater.from(container.context) val view = layoutInflater.inflate(holderResId, container, false) var specificView: View? = null specificResViewId?.let { specificView = view.findViewById(it) } return ViewHolder(view, specificView) } override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { viewHolder.bindView( data[viewHolder.adapterPosition], onBind, itemListener, specificViewListener ) } override fun getItemCount(): Int = data.size fun setData(datas: List) { calculateDiff(datas) } fun addData(newDatas: List) { val list = ArrayList(this.data) list.addAll(newDatas) calculateDiff(list) } fun refreshList() { calculateDiff(data) } fun getData(): List = this.data fun clearData() { calculateDiff(emptyList()) } private fun calculateDiff(newData: List) { diffCallback.setList(data, newData) val result = DiffUtil.calculateDiff(diffCallback) with(data) { clear() addAll(newData) } result.dispatchUpdatesTo(this) } class ViewHolder(view: View, private val specificView: View? = null) : RecyclerView.ViewHolder(view) { private var itemPosition: Int = 0 fun bindView( data: T, onBind: (T, View) -> Unit, itemListener: (T, pos: Int, View) -> Unit, specificViewListener: (T, pos: Int, View) -> Unit ) { itemPosition = adapterPosition with(itemView) { onBind.invoke(data, this) setOnClickListener { itemListener.invoke(data, adapterPosition, this) } } specificView?.setOnClickListener { specificViewListener.invoke(data, adapterPosition, itemView) } } } }