RecylerView优化之高易用HiDataItem组件

目标

高易用HiDataItem

需求

将列表中不同布局的视图,拆分为多种HiDataItem,优势是低耦合和高内聚

成果展示

在这里插入图片描述

用法

HiAdapter2 hiAdapter = new HiAdapter2(this);
  
List<HiDataItem> dataList = new ArrayList<>();
dataList.add(new TopTabDataItem(new ItemData()));//顶部导航栏
dataList.add(new BannerDataItem(new ItemData()));//banner
dataList.add(new GridDataItem(new ItemData()));//运营坑位区域
dataList.add(new ActivityDataItem(new ItemData()));//活动区域
dataList.add(new ItemTabDataItem(new ItemData()));//商品tab栏

hiAdapter.addItems(dataList, false);//体现了程序的可插拔性

疑难点

1.泛型参数实例化
2.itemViewType和HiDataItem实例一一对应

架构设计

在这里插入图片描述

关键代码

HiDataItem.kt

abstract class HiDataItem<DATA, VH : RecyclerView.ViewHolder>(data: DATA) {
    var hiAdapter: HiAdapter? = null
    private var mData: DATA? = null

    init {
        this.mData = data
    }

    fun setAdapter(adapter: HiAdapter) {
        this.hiAdapter = adapter
    }

    abstract fun onBindData(holder: VH, position: Int)

    /**
     * 返回该item的布局资源id
     */
    open fun getItemLayoutRes(): Int {
        return -1
    }

    /**
     * 返回该item的视图view
     */
    open fun getItemView(parent: ViewGroup): View? {
        return null
    }

    /**
     * 刷新列表
     */
    fun refreshItem() {
        if (hiAdapter != null) {
            hiAdapter!!.refreshItem(this)
        }
    }

    /**
     * 从列表上删除
     */
    fun removeItem() {
        if (hiAdapter != null) {
            hiAdapter!!.removeItem(this)
        }
    }

    /**
     * 在列表上占据几列
     * 0表示撑满屏幕宽度
     * 1表示在每一行n列中占据1列
     * 以此类推
     */
    open fun getSpanSize(): Int {
        return 0
    }

    /**
     * 该item被滑进屏幕
     */
    open fun onViewAttachedToWindow(holder: VH) {

    }

    /**
     * 该item被滑出屏幕
     */
    open fun onViewDetachedFromWindow(holder: VH) {

    }
}

HiAdapter

override fun getItemViewType(position: Int): Int {
        if (isHeaderPosition(position)) {
            return headers.keyAt(position)
        }

        if (isFooterPosition(position)) {
            //footer位置 应计算下:position=6  headersize=1 footersize=1
            val footerPosition = position - getHeaderSize() - getOriginalItemSize()
            return footers.keyAt(footerPosition)
        }

        val itemPosition = position - headers.size()
        val dataItem = dataSets.get(itemPosition)
        val type = dataItem.javaClass.hashCode()
        if (typeArrays.indexOfKey(type) < 0) {
            typeArrays.put(type, dataItem)
        }
        return type
    }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        if (headers.indexOfKey(viewType) >= 0) {
            val view = headers[viewType]
            return object : RecyclerView.ViewHolder(view) {}
        }

        if (footers.indexOfKey(viewType) >= 0) {
            val view = footers[viewType]
            return object : RecyclerView.ViewHolder(view) {}
        }

        val dataItem = typeArrays.get(viewType)
        var view: View? = dataItem.getItemView(parent)
        if (view == null) {
            val layoutRes = dataItem.getItemLayoutRes()
            if (layoutRes < 0) {
                RuntimeException("DataItem:" + dataItem.javaClass.name + " must override getItemView or getItemLayoutRes.")
            }
            view = mInflater!!.inflate(layoutRes, parent, false)
        }
        return createViewHolderInternal(dataItem.javaClass, view!!)
    }
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        super.onAttachedToRecyclerView(recyclerView)

        val layoutManager = recyclerView.layoutManager
        if (layoutManager is GridLayoutManager) {
            val spanCount = layoutManager.spanCount
            layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
                override fun getSpanSize(position: Int): Int {

                    if (isHeaderPosition(position) || isFooterPosition(position)) {
                        return spanCount //撑满屏幕
                    }

                    val itemPosition = position - getHeaderSize()
                    if (itemPosition < dataSets.size) {
                        val dataItem = dataSets.get(itemPosition)
                        if (dataItem != null) {
                            val spanSize = dataItem.getSpanSize()
                            return if (spanSize <= 0) spanCount else spanSize
                        }
                    }
                    return spanCount
                }
            }
        }
    }
private fun createViewHolderInternal(
        javaClass: Class<HiDataItem<*, out RecyclerView.ViewHolder>>,
        view: View
    ): RecyclerView.ViewHolder {
        val superClass = javaClass.genericSuperclass
        if (superClass is ParameterizedType) {
            val arguments = superClass.actualTypeArguments
            for (argument in arguments) {
                if (argument is Class<*> && RecyclerView.ViewHolder::class.java.isAssignableFrom(
                        argument
                    )
                ) {
                    try {
                        return argument.getConstructor(View::class.java)
                            .newInstance(view) as RecyclerView.ViewHolder
                    } catch (e: Throwable) {
                        e.printStackTrace()
                    }
                }
            }
        }
        return object : RecyclerView.ViewHolder(view) {}
    }
  • 16
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值