利用lambda簡化RecyclerView.Adapter
每次出現新的列表,一般我們會新建一個類去繼承RecyclerView.Adapter然後覆寫其中方法。一次兩次還好,但很多次之後呢?你是否會不厭其煩?想必我們在實際應用中也不會只有一個或兩個列表,隨着列表的增多,我們寫了越來越多的Adapter,但其中大部分代碼是相同的,卻不能複用,同時,我相信隨着自定義的Adapter越來越多,管理也會越加複雜,這對我們程序猿來說怎麼可以忍受。所以我正好利用kotlin的lambda表達式來消除我們冗餘的代碼。
下面是自定義的Adapter,有了它我們就不需要每次再再做重複的勞動了。
class ViewAdapter<T, VH : ViewHolder>(
@LayoutRes private val layoutResId: Int,
val data: MutableList<T> = mutableListOf()) :
RecyclerView.Adapter<VH>() {
constructor(
@LayoutRes layoutResId: Int,
data: MutableList<T> = mutableListOf(),
@Suppress("UNCHECKED_CAST")
clazz: Class<VH>
) : this(layoutResId, data) {
this.clazz = clazz
}
@Suppress("UNCHECKED_CAST")
private var clazz: Class<VH> = ViewHolder::class.java as java.lang.Class<VH>
private var cons: Constructor<VH>? = null
@Suppress("UNCHECKED_CAST")
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
val itemView = parent.context.inflate(layoutResId, parent)
.apply { setOnClickListener { onItemClick?.invoke(it, it.tag as Int) } }
if (cons == null)
//itemView: View, parent: ViewGroup, viewType: Int
cons = clazz.getConstructor(View::class.java, ViewGroup::class.java, Int::class.java)
return cons!!.newInstance(itemView, parent, viewType)
}
override fun onBindViewHolder(holder: VH, position: Int) {
holder.itemView.tag = position
onBind(holder, data[position])
}
override fun getItemCount(): Int {
return data.size
}
fun setOnBindListener(listener: (VH, T) -> Unit) {
this.onBind = listener
}
fun setOnItemClickListener(listener: (view: View, position: Int) -> Unit) {
this.onItemClick = listener
}
fun replaceAll(list: List<T>) {
data.clear()
data.addAll(0, list)
notifyDataSetChanged()
}
private var onItemClick: ((view: View, position: Int) -> Unit)? = null
private lateinit var onBind: (VH, T) -> Unit
}
然後我們就可以只通過下面的方式來設置RecyclerView的Adapter了
private lateinit var adapter: ViewAdapter<WeekLesson, ViewHolder>
adapter = ViewAdapter(R.layout.class_schedule_item)
adapter.setOnBindListener { viewHolder, classItem ->
//Use your viewHolder
}
adapter.setOnItemClickListener { view, position ->
}
recyclerView.layoutManager = LinearLayoutManager(context)
recyclerView.adapter = adapter
這裏需要注意的是setOnItemClickListener
並不是必須的,而setOnBindListener
則是必須的,因爲要在onBindViewHolder
的時候要回調。
ViewHolder需要實現這樣一個構造參數(itemView: View, parent: ViewGroup, viewType: Int)
第一個參數是每一項的View,第二個參數在這裏即爲RecyclerView的父佈局,第三個參數爲你自己定義的ViewType。
data可以通過adapter.data訪問
,我們可以在創建Adapter的時候傳入數據集合,也可以在創建之後再更新
然後就可以開開心心的寫代碼了,再也不用重複那些枯燥的操作啦。另外還有一種方式,就是通過自定義Android Studio模板代碼的方式讓IDE來幫我們自動創建並完成一些重複代碼。