BaseRecyclerViewAdapterHelper 4.0版本 MutiItemAdapter中添加Holder的方式是否可以更简练些,下面是我的一些尝试

uxh89sit  于 4个月前  发布在  其他
关注(0)|答案(9)|浏览(97)

其实在MultiItemAdapter添加各种addItemType会导致代码冗余的很,适当的抽离和使用反射会使代码简介很多很多,比如我在项目中的尝试:

class DetailsAdapter : BaseMultiItemAdapter<Floors>() {
    init {
        // 根据type添加返回type 滑动时会根据对应额Position去创建对应的Holder
        onItemViewType { position, list ->
            list[position].itemType
        }

        
        addDetailsVH(T_BRAND_HEADER.hashCode(), GDBrandHeaderVH::class.java, R.layout.item_vh_details_brand_header)
        addDetailsVH(T_TOP_BANNER.hashCode(), GDTopBannerVH::class.java, R.layout.item_vh_details_top_banner) 
        addDetailsVH(T_PRESALE_PRICE.hashCode(), GDPresalePricesVH::class.java,R.layout.item_vh_details_presale_prices)
        addDetailsVH(T_ACTIVITY_PRICE.hashCode(), GDActivityPricesVH::class.java, R.layout.item_vh_activity_prices)
       ......
    }

   /**
* 通过传递的过来的Class类型,创建出对应的ViewHolder
*/
    private fun <E : DetailsEntity, T : BaseGDVH<E>> addDetailsVH(
        itemType: Int, // holder类型
        vh: Class<T>,  // holder类名
        @LayoutRes layoutId: Int // holder布局
    ) {
        addItemType(itemType, object : OnMultiItemAdapterListener<DetailsEntity?, T> {
            override fun onCreate(context: Context, parent: ViewGroup, viewType: Int): T {
                // 获取到默认的构造方法
                val constructors = vh.declaredConstructors[0]
                // 获取到绑定的view
                val view = LayoutInflater.from(context).inflate(layoutId, parent, false)
                return constructors.newInstance(view) as T
            }

            override fun onBind(holder: T, position: Int, item: DetailsEntity?) {
                if (item == null) {
                    holder.onHiddenVh()
                    return
                }

                holder.onBindData(item as E)
            }

            // 商详的holder都是跨满屏幕
            override fun isFullSpanItem(itemType: Int): Boolean {
                return true
            }
        })
    }
}

/**
* 抽离出来的一个基类,限定绑定类型,方便以后扩展
*/
abstract class BaseGDVH<T : DetailsEntity>(view: View) : RecyclerView.ViewHolder(view) {
    abstract fun onBindData(data: T)

    // 当类型解析失败(不匹配),或者是数据为空时,需要将当前的Holder直接隐藏掉
    fun onHiddenVh() {
        itemView.layoutParams.apply {
            width = 0
            height = 0
        }
        itemView.visibility = View.GONE
    }
}
ctrmrzij

ctrmrzij1#

其实在MultiItemAdapter添加各种addItemType会导致代码冗余的很,适当的抽离和使用反射会使代码简介很多很多,比如我在项目中的尝试:

class DetailsAdapter : BaseMultiItemAdapter<Floors>() {
    init {
        // 根据type添加返回type 滑动时会根据对应额Position去创建对应的Holder
        onItemViewType { position, list ->
            list[position].itemType
        }

        
        addDetailsVH(T_BRAND_HEADER.hashCode(), GDBrandHeaderVH::class.java, R.layout.item_vh_details_brand_header)
        addDetailsVH(T_TOP_BANNER.hashCode(), GDTopBannerVH::class.java, R.layout.item_vh_details_top_banner) 
        addDetailsVH(T_PRESALE_PRICE.hashCode(), GDPresalePricesVH::class.java,R.layout.item_vh_details_presale_prices)
        addDetailsVH(T_ACTIVITY_PRICE.hashCode(), GDActivityPricesVH::class.java, R.layout.item_vh_activity_prices)
       ......
    }

   /**
* 通过传递的过来的Class类型,创建出对应的ViewHolder
*/
    private fun <E : DetailsEntity, T : BaseGDVH<E>> addDetailsVH(
        itemType: Int, // holder类型
        vh: Class<T>,  // holder类名
        @LayoutRes layoutId: Int // holder布局
    ) {
        addItemType(itemType, object : OnMultiItemAdapterListener<DetailsEntity?, T> {
            override fun onCreate(context: Context, parent: ViewGroup, viewType: Int): T {
                // 获取到默认的构造方法
                val constructors = vh.declaredConstructors[0]
                // 获取到绑定的view
                val view = LayoutInflater.from(context).inflate(layoutId, parent, false)
                return constructors.newInstance(view) as T
            }

            override fun onBind(holder: T, position: Int, item: DetailsEntity?) {
                if (item == null) {
                    holder.onHiddenVh()
                    return
                }

                holder.onBindData(item as E)
            }

            // 商详的holder都是跨满屏幕
            override fun isFullSpanItem(itemType: Int): Boolean {
                return true
            }
        })
    }
}

/**
* 抽离出来的一个基类,限定绑定类型,方便以后扩展
*/
abstract class BaseGDVH<T : DetailsEntity>(view: View) : RecyclerView.ViewHolder(view) {
    abstract fun onBindData(data: T)

    // 当类型解析失败(不匹配),或者是数据为空时,需要将当前的Holder直接隐藏掉
    fun onHiddenVh() {
        itemView.layoutParams.apply {
            width = 0
            height = 0
        }
        itemView.visibility = View.GONE
    }
}

这样就能省略很多addItemType的重复代码,而用反射单单创建一个实例应该还是比较容易接受的,但目前我遇到一个问题,就是如果才能更优雅的获取到Holder的实例呢,然后在其他特殊场景下进行数据的传递,例如我在列表中有一个Holder的数据需要根据外部的条件随时更改,如何才能优雅且快速的找到目标Holder呢?

vtwuwzda

vtwuwzda2#

看了你的代码,并没有本质变化。对于一个 三方库 来说,这种过渡的封装显得没有必要,反而会丢失更多的自由性,每个人可以安装不同的业务情况,自己去封装个 BaseVH
你所说到的 冗余 问题,其实处理起来很简单,例如 OnMultiItemAdapterListener 可独立成一个class。

wyyhbhjk

wyyhbhjk3#

看了你的代码,并没有本质变化。对于一个 三方库 来说,这种过渡的封装显得没有必要,反而会丢失更多的自由性,每个人可以安装不同的业务情况,自己去封装个 BaseVH 。 你所说到的 冗余 问题,其实处理起来很简单,例如 OnMultiItemAdapterListener 可独立成一个class。

明白了,感谢大佬指导,那咱们的库有没有更优雅的获取Holder实例的方法呢?

a7qyws3x

a7qyws3x4#

最新版本是否同时支持下拉刷新,上拉加载更多和DiffAdapter,这种使用场景较多,希望以后版本中能实现

emeijp43

emeijp435#

最新版本是否同时支持下拉刷新,上拉加载更多和DiffAdapter,这种使用场景较多,希望以后版本中能实现

肯定支持啊

k4emjkb1

k4emjkb16#

看了你的代码,并没有本质变化。对于一个 三方库 来说,这种过渡的封装显得没有必要,反而会丢失更多的自由性,每个人可以安装不同的业务情况,自己去封装个 BaseVH 。 你所说到的 冗余 问题,其实处理起来很简单,例如 OnMultiItemAdapterListener 可独立成一个class。

明白了,感谢大佬指导,那咱们的库有没有更优雅的获取Holder实例的方法呢?

你打个比方呢?是哪里获取 holder ?

2w3kk1z5

2w3kk1z57#

看了你的代码,并没有本质变化。对于一个 三方库 来说,这种过渡的封装显得没有必要,反而会丢失更多的自由性,每个人可以安装不同的业务情况,自己去封装个 BaseVH 。 你所说到的 冗余 问题,其实处理起来很简单,例如 OnMultiItemAdapterListener 可独立成一个class。

明白了,感谢大佬指导,那咱们的库有没有更优雅的获取Holder实例的方法呢?

你打个比方呢?是哪里获取 holder ?

很抱歉,最近需求太多了,一直没顾的上回复大佬您,具体的场景大概可以理解为 在一个列表中,存在很多Type的item,其中有一项是视频、一项是轮播图,假设这两种都有很多个,这时,当切换页面和进入后台时,如果才能合理的找到对应的Holder,然后将其中的Holder关闭播放/轮播呢?

rwqw0loc

rwqw0loc8#

看了你的代码,并没有本质变化。对于一个 三方库 来说,这种过渡的封装显得没有必要,反而会丢失更多的自由性,每个人可以安装不同的业务情况,自己去封装个 BaseVH 。 你所说到的 冗余 问题,其实处理起来很简单,例如 OnMultiItemAdapterListener 可独立成一个class。

明白了,感谢大佬指导,那咱们的库有没有更优雅的获取Holder实例的方法呢?

你打个比方呢?是哪里获取 holder ?

很抱歉,最近需求太多了,一直没顾的上回复大佬您,具体的场景大概可以理解为 在一个列表中,存在很多Type的item,其中有一项是视频、一项是轮播图,假设这两种都有很多个,这时,当切换页面和进入后台时,如果才能合理的找到对应的Holder,然后将其中的Holder关闭播放/轮播呢?

override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {

}

这个方法不能做到么?

alen0pnh

alen0pnh9#

看了你的代码,并没有本质变化。对于一个 三方库 来说,这种过渡的封装显得没有必要,反而会丢失更多的自由性,每个人可以安装不同的业务情况,自己去封装个 BaseVH 。 你所说到的 冗余 问题,其实处理起来很简单,例如 OnMultiItemAdapterListener 可独立成一个class。

明白了,感谢大佬指导,那咱们的库有没有更优雅的获取Holder实例的方法呢?

你打个比方呢?是哪里获取 holder ?

很抱歉,最近需求太多了,一直没顾的上回复大佬您,具体的场景大概可以理解为 在一个列表中,存在很多Type的item,其中有一项是视频、一项是轮播图,假设这两种都有很多个,这时,当切换页面和进入后台时,如果才能合理的找到对应的Holder,然后将其中的Holder关闭播放/轮播呢?

override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {

}

这个方法不能做到么?

在Fragment场景下中,切换不同的Fragment时,这个方法是不会执行的,还有前后台切换也不会执行

相关问题