Android 自定义通用的RecyclerView Adapter

前言

我们在使用RecyclerView的时候,总是需要写很多的AdapterViewholder,其中又有很多重复无用的代码,那能不能自己实现一套通过的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

最终效果
实现效果

结语

代码整体下来还是比较简单,重要的是思想,当我们不停的写代码的时候,有时候也要停下来思考下,这样写好不好,有没有好的方法方式能够节省代码量,解决一些痛点,这样才会有所进步。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值