Android RecyclerView+Lifecycle+ViewBinding简化使用

2 篇文章 0 订阅
1 篇文章 0 订阅

前言

之前一直使用kotlin,kotlin的插件挺好用的,现在建议使用ViewBinding,索性将获取布局方式修改为ViewBinding,之前了解Jetpack系列感觉Lifecycle挺好用的,将Android中组件化提高了一个档次,所以有了以下封装,好了废话不多说直接上代码.

1.先上接口,此接口主要将Adapter中需要实现的功能代理出去
interface AdapterImpl<B: Any, VB: ViewBinding> {
    /// 初始化viewBinding
    fun initViewHolder(parent: ViewGroup, viewType: Int): ViewBindingRvCurrencyHolder<VB>

    /// 实际处理
    fun onBindViewHolder(holder: ViewBindingRvCurrencyHolder<VB>, position: Int, binding: VB, bean: B)
}
// 通用ViewHolder
open class ViewBindingRvCurrencyHolder<VB : ViewBinding>(val binding: VB): RecyclerView.ViewHolder(binding.root) {

    // 设置item点击事件
    fun setItemOnClickListener(click: View.OnClickListener) {
        binding.root.setOnClickListener(click)
    }

    // 设置item点击事件
    fun setItemOnClickListener(click: (View) -> Unit) {
        binding.root.setOnClickListener(click)
    }
}
2. Adapter封装
abstract class RvCurrencyAdapter<T : Any, VH : RecyclerView.ViewHolder>(private val context: Context) :
    RecyclerView.Adapter<VH>() {

    protected val inflater: LayoutInflater = LayoutInflater.from(context)

    // 数据源
    open var dataList: MutableList<T> = mutableListOf()
        set(value) {
            field = value
            notifyItemRangeChanged(0, value.size)
        }

    // 添加一条数据刷新
    fun addItemData(data: T) {
        dataList.add(data)
        notifyDataSetChanged()
    }

    // 向末尾添加数据
    fun addItemDataAll(data: List<T>) {
        dataList.addAll(data)
        notifyDataSetChanged()
    }

    abstract override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH

    override fun onBindViewHolder(holder: VH, position: Int) {
        onBindViewHolder(holder, holder.adapterPosition, dataList[holder.adapterPosition])
    }

    override fun getItemCount(): Int = dataList.size

    abstract fun onBindViewHolder(
        holder: VH,
        position: Int,
        bean: T
    )

    /// 创建ViewBindingRvCurrencyHolder对象
    inline fun <reified T : ViewBinding> bindingViewHolderNew(parent: ViewGroup): ViewBindingRvCurrencyHolder<T> {
        val method = T::class.java.getMethod("inflate", LayoutInflater::class.java, ViewGroup::class.java, Boolean::class.java)
        val binding = method.invoke(null, LayoutInflater.from(parent.context), parent, false) as T
        return ViewBindingRvCurrencyHolder(binding)
    }
}
/**
 * ViewBinding与Adapter结合使用
 */
abstract class ViewBindingRvCurrencyAdapter<T : Any, VB : ViewBinding>(val context: Context) :
    RvCurrencyAdapter<T, ViewBindingRvCurrencyHolder<VB>>(context) {
    
    override fun onBindViewHolder(holder:ViewBindingRvCurrencyHolder<VB>, position: Int, bean: T) {
        onBindViewHolder(holder, position, holder.binding, bean)
    }

    abstract fun onBindViewHolder(holder: ViewBindingRvCurrencyHolder<VB>, position: Int, binding: VB, bean: T)
}
/**
 * 单布局, 将rv功能封装对外提供
 */
class SingleLayoutBaseNewAdapter<B: Any, VB: ViewBinding>(context: Context, private val impl: AdapterImpl<B, VB>): ViewBindingRvCurrencyAdapter<B, VB>(context) {
    override fun onCreateViewHolder(parent: ViewGroup,viewType: Int): ViewBindingRvCurrencyHolder<VB> {
        return impl.initViewHolder(parent, viewType)
    }

    override fun onBindViewHolder(holder: ViewBindingRvCurrencyHolder<VB>, position: Int, binding: VB, bean: B) {
        impl.onBindViewHolder(holder, position, binding, bean)
    }
}
3.RecyclerView的封装
/**
 * 简化RecyclerView的使用
 * B: 数据集
 * VB: ViewBinding绑定布局
 * 使用: 
 *  1.继承BaseRecyclerView
 *  2.在activity中使用lifecycle.addObserver(rvId)监听控件
 */
abstract class BaseRecyclerView<B: Any, VB: ViewBinding>: RecyclerView, LifecycleObserver {

    // 定义适配器
    private lateinit var baseAdapter: SingleLayoutBaseNewAdapter<B, VB>

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
    }

    // 返回新adapter
    fun getBaseAdapter(): SingleLayoutBaseNewAdapter<B, VB> = baseAdapter

    /// 初始化viewBinding
    protected abstract fun initViewHolder(parent: ViewGroup, viewType: Int): ViewBindingRvCurrencyHolder<VB>

    /// 实际处理
    protected abstract fun onBindViewHolder(holder: ViewBindingRvCurrencyHolder<VB>, position: Int, binding: VB, bean: B)

    /// rv布局方式
    protected abstract fun layoutManager(): LayoutManager

    // 添加一条数据刷新
    fun addItemData(data: B) {
        getBaseAdapter().addItemData(data)
    }

    // 向末尾添加数据
    fun addItemDataAll(data: List<B>) {
        getBaseAdapter().addItemDataAll(data)
    }

    /// 初始化
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    private fun onCreate() {
        baseAdapter = SingleLayoutBaseNewAdapter(context, object: AdapterImpl<B, VB> {
            override fun initViewHolder(parent: ViewGroup, viewType: Int): ViewBindingRvCurrencyHolder<VB> {
                return this@BaseRecyclerView.initViewHolder(parent, viewType)
            }

            override fun onBindViewHolder(holder: ViewBindingRvCurrencyHolder<VB>, position: Int, binding: VB, bean: B) {
                this@BaseRecyclerView.onBindViewHolder(holder, position, binding, bean)
            }

        })

        this.adapter = baseAdapter
        this.layoutManager = layoutManager()
    }
}
4. 使用
class MyRecyclerView: BaseRecyclerView<DemoHttpBean, RvDemoHttpBinding> {
    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
    }

    override fun initViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): ViewBindingRvCurrencyHolder<RvDemoHttpBinding> = getBaseAdapter().bindingViewHolderNew(parent)

    override fun onBindViewHolder(
        holder: ViewBindingRvCurrencyHolder<RvDemoHttpBinding>,
        position: Int,
        binding: RvDemoHttpBinding,
        bean: DemoHttpBean
    ) {
        holder.binding.tvTitle.text = bean.title
        holder.binding.tvContent.text = bean.content
        Log.e("fyc", ">>>>>>>>>>>>>> onBindViewHolder <<<<<<<<<<<<<<<<<<<<<")

        holder.setItemOnClickListener {
            Toast.makeText(context, "item点击事件触发", Toast.LENGTH_LONG).show()
        }
    }

    override fun layoutManager(): LayoutManager = LinearLayoutManager(context)
}
class TestRvOneAc : AppCompatActivity() {
    private val binding: AcTestRvOneBinding by inflate()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycle.addObserver(binding.rvTestData)
    }

    override fun onDestroy() {
        super.onDestroy()
    }
}
总结

整体使用比较简单,不用担心性能问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值