前言
我们在使用RecyclerView
的时候,总是需要写很多的Adapter
和Viewholder
,其中又有很多重复无用的代码,那能不能自己实现一套通过的CommonAdapter
减少重复代码呢?
具体实现
- 打造通用的
ViewHolder
package com.crystal.view
import android.util.SparseArray
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
/**
* 打造通用的ViewHolder
*/
class CommonViewHolder(itemView: View) : ViewHolder(itemView) {
/**
* 用来缓存view集合
*/
private var mViews = SparseArray<View>()
/**
* 通过id设置text文字
*/
fun setText(viewId: Int, text: CharSequence): CommonViewHolder {
val tv = getView<TextView>(viewId)
tv.text = text
return this
}
/**
* 通过id设置view的显示和隐藏
*/
fun setViewVisibility(viewId: Int, visibility: Int): ViewHolder {
val view = getView<View>(viewId)
view.visibility = visibility
return this
}
/**
* 设置图片资源
*/
fun setImageResource(viewId: Int, resourceId: Int): ViewHolder {
val view = getView<ImageView>(viewId)
view.setImageResource(resourceId)
return this
}
/**
* 设置条目点击事件
*/
fun setOnItemClickListener(listener: View.OnClickListener) {
itemView.setOnClickListener(listener)
}
/**
* 设置条目长按点击事件
*/
fun setOnItemLongClickListener(listener: View.OnLongClickListener) {
itemView.onLongClickListener = listener
}
private fun <T : View> getView(viewId: Int): T {
var view = mViews[viewId]
if (view == null) {
view = itemView.findViewById(viewId)
mViews.put(viewId, view)
}
return view as T
}
}
这里的代码可以按需添加通用代码,如按url
加载图片、添加事件监听等等。
- 打造通用的
Adapter
package com.crystal.view
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
/**
* 打造通用的recycle adapter
*/
abstract class CommonRecyclerAdapter<T>(
private val context: Context, private val datas: List<T>
) : RecyclerView.Adapter<CommonViewHolder>() {
private var multiSupport: MultiTypeSupport<T>? = null
constructor(context: Context, datas: List<T>, multiSupport: MultiTypeSupport<T>) : this(
context,
datas
) {
this.multiSupport = multiSupport
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CommonViewHolder {
return if (multiSupport != null) {
val view = LayoutInflater.from(context).inflate(viewType, parent, false)
CommonViewHolder(view)
} else {
val view = LayoutInflater.from(context).inflate(bindLayoutId(), parent, false)
CommonViewHolder(view)
}
}
override fun getItemViewType(position: Int): Int {
if (multiSupport != null) {
return multiSupport!!.getLayoutId(datas[position], position)
}
return super.getItemViewType(position)
}
override fun onBindViewHolder(holder: CommonViewHolder, position: Int) {
convert(holder, datas[position])
}
override fun getItemCount(): Int {
return datas.size
}
abstract fun convert(holder: CommonViewHolder, item: T)
abstract fun bindLayoutId(): Int
}
/**
* 用于加载不同的布局文件
*/
interface MultiTypeSupport<T> {
fun getLayoutId(item: T, position: Int): Int
}
测试效果
- 先自定义
adapter
继承通用的adapter
class CommonItemAdapter(
context: Context, datas: List<CommonData>
) : CommonRecyclerAdapter<CommonData>(context, datas, object : MultiTypeSupport<CommonData> {
override fun getLayoutId(item: CommonData, position: Int): Int {
return if (item.text.toInt() % 2 == 0) {
R.layout.item_layout_recycler_two
} else {
R.layout.item_layout_recycler_one
}
}
}) {
override fun convert(holder: CommonViewHolder, item: CommonData) {
holder.setText(R.id.tv, item.text)
holder.setImageResource(R.id.iv, item.res)
}
override fun bindLayoutId(): Int {
return R.layout.item_layout_recycler_one
}
}
- 代码中使用
for (i in 0..50) {
list.add(CommonData(R.mipmap.ic_launcher, "$i"))
}
val rlv = findViewById<RecyclerView>(R.id.rlv)
rlv.layoutManager = LinearLayoutManager(this)
rlv.addItemDecoration(ItemDecoration(getDrawable(R.drawable.shape_item_decoration)))
val adapter = CommonItemAdapter(this, list)
rlv.adapter = adapter
最终效果
结语
代码整体下来还是比较简单,重要的是思想,当我们不停的写代码的时候,有时候也要停下来思考下,这样写好不好,有没有好的方法方式能够节省代码量,解决一些痛点,这样才会有所进步。