改造万能适配器,结合XRefreshView刷新库使用

随着RecyclerView高度自定义的特性(没错,RecyclerView真的可以为所欲为!),越来越多的开发者选择使用RV进行开发,进而诞生了相关RV的很多框架,今天我要说的就是关注度很高的万能适配器BaseRecyclerViewAdapterHelper和一个支持多种View的加载框架XRefreshView

本人在实际的开发过程中使用BaseRecyclerViewAdapterHelper(万能适配器)遇到了一个问题,就是做分页加载的时候,当加载更多数据不满一屏幕的时候,如果是调用loadMoreComplete()方法,会出现无限加载的情况。这个问题可以通过判断如果数据不满指定分页条数,就调用loadMoreEnd()方法结束加载更多:

if (current_size < page_size) {
	//数据全部数据
	adapter.loadMoreEnd();
} else {
	adapter.loadMoreComplete();
}

但是这样就会存在一个问题,假如一次请求20条数据,但是这个20条数据并不够一屏时,就还是会出现无限加载的问题。因此我就想到了用XRefreshView框架实现上拉加载,随后又遇到了问题,因为XRefreshView有自己指定的Adapter,不能用万能适配器,因此又卡住了。最后我想到了解决办法,就是将两者结合,自己写一个Adapter继承XRefreshView的适配器BaseRecyclerAdapter。

思路:写一个类,继承自BaseRecyclerAdapter,并通过泛型指定ViewHolder和数据类型Bean,实现getAdapterItemCount()和onCreateViewHolder()方法。然后通过反射拿到ViewHolder,然后通过返回holder,在具体的实现类中来设置具体的数据。

先看一下效果图:


代码如下(Kotlin版本):

abstract class BaseTabRecyclerAdapter<VH : RecyclerView.ViewHolder, T> : BaseRecyclerAdapter<VH> {

    private lateinit var data: List<T>
    private var layoutId: Int = -1
    private lateinit var listener: OnItemClickListener
    private lateinit var longClickListener: OnItemLongClickListener

    constructor(data: List<T>) {
        this.data = data
    }

    constructor(layoutId: Int) {
        this.layoutId = layoutId
    }

    constructor(data: List<T>, layoutId: Int) {
        this.data = data
        this.layoutId = layoutId
    }


    override fun getViewHolder(view: View?): VH {
        return createBaseViewHolder(view!!)
    }

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int, isItem: Boolean): VH {
        if (this.layoutId == -1) {
            IllegalArgumentException("The current layout is not set, please set the layout")
        }
        val rootView = LayoutInflater.from(parent?.context).inflate(layoutId, parent, false)
        return createBaseViewHolder(rootView)
    }

    override fun getAdapterItemCount(): Int {
        return data?.size
    }

    override fun onBindViewHolder(holder: VH, position: Int, isItem: Boolean) {
        val t = data?.get(position)
        bindClickListener(holder,position)
        convert(holder, t)
    }

    open fun setItemViewId(layoutId: Int) {
        this.layoutId = layoutId
    }

    /**
     * 绑定监听
     */
    private fun bindClickListener(holder: VH, position: Int) {
        if (holder == null) return
        val itemView = holder.itemView ?: return
        //点击事件
        if (listener != null)
            itemView.setOnClickListener { listener.onItemClick(position) }
        //长按事件
        if (longClickListener != null)
            itemView.setOnLongClickListener {
                longClickListener.onItemLongClick(position)
                true
            }

    }

    /**
     * 自己实现
     */
    abstract fun convert(holder: VH, t: T)

    /**
     * 创建ViewHolder
     */
    private fun createBaseViewHolder(view: View): VH {
        var temp: Class<*>? = javaClass
        var z: Class<*>? = null
        while (z == null && null != temp) {
            z = getInstancedGenericVHClass(temp)
            temp = temp.superclass
        }
        val vh: VH?
        // 泛型擦除会导致z为null
        if (z == null) {
            vh = BaseViewHolder(view) as VH
        } else {
            vh = createGenericVHInstance(z, view)
        }
        return vh ?: BaseViewHolder(view) as VH
    }

    private fun getInstancedGenericVHClass(z: Class<*>): Class<*>? {
        val type = z.genericSuperclass
        if (type is ParameterizedType) {
            val types = type.actualTypeArguments
            for (temp in types) {
                if (temp is Class<*>) {
                    if (BaseViewHolder::class.java.isAssignableFrom(temp)) {
                        return temp
                    }
                } else if (temp is ParameterizedType) {
                    val rawType = type.rawType
                    if (rawType is Class<*> && BaseViewHolder::class.java.isAssignableFrom(rawType)) {
                        return rawType
                    }
                }
            }
        }
        return null
    }

    private fun createGenericVHInstance(z: Class<*>, view: View): VH? {
        try {
            val constructor: Constructor<*>
            // inner and unstatic class
            if (z.isMemberClass && !Modifier.isStatic(z.modifiers)) {
                constructor = z.getDeclaredConstructor(javaClass, View::class.java)
                constructor.isAccessible = true
                return constructor.newInstance(this, view) as VH
            } else {
                constructor = z.getDeclaredConstructor(View::class.java)
                constructor.isAccessible = true
                return constructor.newInstance(view) as VH
            }
        } catch (e: NoSuchMethodException) {
            e.printStackTrace()
        } catch (e: IllegalAccessException) {
            e.printStackTrace()
        } catch (e: InstantiationException) {
            e.printStackTrace()
        } catch (e: InvocationTargetException) {
            e.printStackTrace()
        }

        return null
    }

    companion object {
        open class BaseViewHolder(view: View) : RecyclerView.ViewHolder(view)
        interface OnItemClickListener {
            fun onItemClick(position: Int)
        }

        interface OnItemLongClickListener {
            fun onItemLongClick(position: Int)
        }
    }


    fun setOnItemClickListener(listener: OnItemClickListener) {
        this.listener = listener
    }

    fun setOnItemLongClickListener(longClickListener: OnItemLongClickListener) {
        this.longClickListener = longClickListener
    }

}

这样就可以使用XRefreshView做上拉加载,下拉刷新的万能适配了。

简单的使用方式:

class TabAdapter(var context: Context, data: List<String>) : BaseQuickAdapter<String, TabAdapter.Companion.TabViewHolder>(R.layout.recycler_tab_item_layout,data) {

    override fun convert(holder: TabViewHolder, p1: String?) {
        holder.textView.text = p1
    }

    companion object {
        class TabViewHolder(view: View) : BaseViewHolder(view) {
            var textView: TextView = view.tv_item
        }
    }

}

在此要感谢XRefreshView和BaseRecyclerViewAdapterHelper的作者。

https://github.com/huxq17/XRefreshView

https://github.com/CymChad/BaseRecyclerViewAdapterHelper



猜你喜欢

转载自blog.csdn.net/wangwasdf/article/details/80619524