资讯专栏INFORMATION COLUMN

一劳永逸——RecyclerView无类型强转的通用ViewHolder

layman / 825人阅读

摘要:我们知道在一般的列表视图中绑定不同类型的列表项子视图是通过各种类型的比如不同数据对不同视图控件的操作是以实现各种子类的方式实现的能不能只用一种类型的视图来涵盖所有的类型听起来有些不可思议每种需要绑定的控件千差万别怎么抽象这些控件呢但实际上是

我们知道在一般的列表视图(recyclerView)中绑定不同类型的列表项子视图是通过各种类型的ViewHolder(比如recyclerView.ViewHolder). 不同数据对不同视图控件的操作是以实现各种ViewHolder子类的方式实现的.
能不能只用一种类型的视图来涵盖所有的ViewHolder类型? 听起来有些不可思议, 每种ViewHolder需要绑定的控件千差万别, 怎么抽象这些控件呢? 但实际上是可以实现的.

在support.v7.preference库中作者就用了一种方式实现这种效果:

public class PreferenceViewHolder extends RecyclerView.ViewHolder {
    private final SparseArray mCachedViews = new SparseArray<>(4);

    public View findViewById(@IdRes int id) {
        final View cachedView = mCachedViews.get(id);
        if (cachedView != null) {
            return cachedView;
        } else {
            final View v = itemView.findViewById(id);
            if (v != null) {
                mCachedViews.put(id, v);
            }
            return v;
        }
    }
}

这样外部只需通过findViewById来找到各种各样的控件实例来进行数据绑定即可, 但是声明的ViewHolder却只需一种! 仔细想想这种通过SparseArray持有的方式其实非常巧妙, 真正将ViewHolder作为各种视图的持有者(Holder)不用再区分类型, 可谓实至名归.

稍加改造就可以和新API的findViewById风格完全保持一致(我们姑且叫做ItemViewHolder, 抽象所有列表视图子视图):

public class ItemViewHolder extends RecyclerView.ViewHolder  {
    private final SparseArrayCompat mCached = new SparseArrayCompat<>(10);

    public ItemViewHolder(View itemView) {
        super(itemView);
    }

    public  T findViewById(@IdRes int resId) {
        int pos = mCached.indexOfKey(resId);
        View v;
        if (pos < 0) {
            v = itemView.findViewById(resId);
            mCached.put(resId, v);
        } else {
            v = mCached.valueAt(pos);
        }
        @SuppressWarnings("unchecked")
        T t = (T) v;
        return t;
    }
}

其实RecyclerView.ViewHolder本身就应该设计成这种方式, 并且声明成final强制移除各种Viewholder类型的强转.

所以还是要多看官方成熟的库, 他们的设计和实现都是经过千锤百炼, 对学习非常有益处.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/14988.html

相关文章

  • Kotlin入门(23)适配器的进阶表达

    摘要:有鉴于此,循环视图的适配器把视图持有者的重用逻辑剥离出来,由系统自行判断并处理持有者的重用操作。至此本节的适配器实现过程终于落下帷幕,一路上可谓是过五关斩六将,硬生生把数十行的代码压缩到不到十行的代码,经过不断迭代优化方取得如此彪炳战绩。前面在介绍列表视图和网格视图时,它们的适配器代码都存在视图持有者ViewHolder,因为Android对列表类视图提供了回收机制,如果某些列表项在屏幕上看...

    Raaabbit 评论0 收藏0
  • Android 初级面试者拾遗(前台界面篇)之 ListView 和 RecyclerView

    摘要:方法根据子项所处的位置判断具体类型并返回。调用方法解除子项与之间的关联。自定义适配器适配器继承自,并将泛型指定为内部类。使用支持多种布局方式借助能够灵活地将列表控件放入不同的容器。 ListView 和 RecyclerView 最常用和最难用的控件 由于手机屏幕空间有限,无法显示全部内容。当有大量数据需要展示的时候,借助列表控件。通过手指上下滑动,使得屏幕内外的数据不断进出。 最基本...

    wangzy2019 评论0 收藏0
  • Android 初级面试者拾遗(前台界面篇)之 ListView 和 RecyclerView

    摘要:方法根据子项所处的位置判断具体类型并返回。调用方法解除子项与之间的关联。自定义适配器适配器继承自,并将泛型指定为内部类。使用支持多种布局方式借助能够灵活地将列表控件放入不同的容器。 ListView 和 RecyclerView 最常用和最难用的控件 由于手机屏幕空间有限,无法显示全部内容。当有大量数据需要展示的时候,借助列表控件。通过手指上下滑动,使得屏幕内外的数据不断进出。 最基本...

    MartinDai 评论0 收藏0
  • RecyclerView问题汇总

    摘要:缺点自动装箱的存在意味着每一次插入都会有额外的对象创建。对象本身是一层额外需要被创建以及被垃圾回收的对象。相较于我们舍弃了和类型的放弃了并依赖于二分法查找。 目录介绍 25.0.0.0 请说一下RecyclerView?adapter的作用是什么,几个方法是做什么用的?如何理解adapter订阅者模式? 25.0.0.1 ViewHolder的作用是什么?如何理解ViewHolder...

    boredream 评论0 收藏0
  • 学习安卓开发[3]

    摘要:在上一篇学习安卓开发在中托管中了解了使用的好处和方法,本次记录的是在进行列表展示时的使用。的作用的是按需创建对象,当被滑动到屏幕外后,便会将其回收再利用。基本的使用方式如下,其中为单个列表项的名称。在上一篇学习安卓开发[2] - 在Activity中托管Fragment中了解了使用Fragment的好处和方法,本次记录的是在进行列表展示时RecyclerView的使用。 RecyclerV...

    xingqiba 评论0 收藏0

发表评论

0条评论

layman

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<