现在App大部分都不止一个列表,而每用一次都写一个适配器继承RecyclerView.Adapter重写它的方法。多次使用列表时,这项工作就变得重复冗余。我们可以使用lambda来封装一个可复用的Adapter。
class MyAdapter<T>(
@LayoutRes
private val layoutId: Int
) : RecyclerView.Adapter<MyAdapter.MyHolder>() {
private lateinit var onBind: (list: MutableList<T>, holder: MyHolder, position: Int) -> Unit
private var itemClick: ((view: View, position: Int) -> Unit)? = null
private val list: MutableList<T> = arrayListOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyHolder {
val itemView = LayoutInflater.from(parent.context)
.inflate(layoutId, parent, false)
val holder = MyHolder(itemView)
itemView.setOnClickListener {
itemClick?.invoke(it, holder.layoutPosition)
}
return holder
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: MyHolder, position: Int) {
onBind.invoke(list, holder, position)
}
fun setItemClickListener(listener: (view: View, position: Int) -> Unit) {
this.itemClick = listener
}
fun setOnBindListener(listener: (list: MutableList<T>, holder: MyHolder, position: Int) -> Unit) {
this.onBind = listener
}
fun replaceAll(data: List<T>) {
list.clear()
list.addAll(data)
notifyDataSetChanged()
}
fun removeItem(position: Int) {
list.removeAt(position)
notifyItemRemoved(position)
notifyDataSetChanged()
}
class MyHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
}
我们使用得时候就可以这样写。
val filmAdapter = MyAdapter<Film>(R.layout.list_film)
filmAdapter.setOnBindListener {
//onBindViewHolder()的逻辑
}
val layoutManager = LinearLayoutManager(context)
layoutManager.orientation = LinearLayoutManager.HORIZONTAL
recyclerView.layoutManager = layoutManager
recyclerView.adapter = filmAdapter
这样无论用多少次列表只需写一个这样的Adapter就行,可以很轻松的构建我们的代码。
这个类接收一个布局的id作为参数。可以通过传入两个lambda表达式onBind和itemClick写入我们的逻辑。其中onBind的逻辑是必须设置的,因为在onBindViewHolder() 需要执行这个lambda表达式。
onBind()有三个参数list、holder、position 通过list可以访问Adapter的数据。通过holder访问View
设置Adapter的数据可以通过replaceAll()方法。