Android RecyclerView分析 第一篇【ChildHelper】

一、在RecyclerView中的位置与角色

在RecyclerView对象创建时,会创建一个 ChildHelper 对象。
在设置layoutManager时,将 RecyclerView中的成员变量 mChildHelper 传进 layoutManager中。

ChildHelper 封装了对 RecyclerView所有子View的所有操作。包括
子View的添加、删除、绑定、解绑、获取子View、判断是否隐藏等。

在RecyclerView 和 layoutManager中所有的 对子View的操作和查询,全部代理给了 ChildHelper。

二、ChildHelper 数据结构

以一个Bucket链条结构,表示一个RecyclerView中所有 Child 的显示/隐藏 状态。
一个Bucket对象是 64bit 存储,1 代表 child hidden,0代表 child 是正常的。

Bucket1 ------------- Bucket0
(Next) -------------- (this)

mData
long1 --------------long0

Child Index
127–64 ----------- 63–0

方向
After ----- 0 ------Before
1000100 0 10000

三、具体用途

最核心与调用次数多的:

  • 查询某个子View 是否是隐藏状态 boolean isHidden(View view)
  • 取子View个数
    int getChildCount() 获取可见View个数
    int getUnfilteredChildCount() 获取所有子View个数
  • 取某个子View
    View getChildAt(int index) 获取可见View中的index位置的View
    View getUnfilteredChildAt(int index) 获取所有子View中的index位置的View

其他的:

void addView(View child, int index, boolean hidden)
void removeView(View view)
void removeAllViewsUnfiltered()

void attachViewToParent(View child, int index, ViewGroup.LayoutParams layoutParams,
            boolean hidden)
void detachViewFromParent(int index)

int indexOfChild(View child)

void hide(View view)
void unhide(View view)

四、ChildHelper的基本调用逻辑

举例说明:

void addView(View child, int index, boolean hidden) {
		// 第一步:更新Bucket链 数据
        final int offset;
        if (index < 0) {
            offset = mCallback.getChildCount();
        } else {
            offset = getOffset(index);
        }
        mBucket.insert(offset, hidden);
        if (hidden) {
            hideViewInternal(child);
        }
        // 第二步:调用callback,执行真正的操作
        mCallback.addView(child, offset);
        if (DEBUG) {
            Log.d(TAG, "addViewAt " + index + ",h:" + hidden + ", " + this);
        }
    }

这里的 mCallback 是 ChildHelper定义的接口:

interface Callback {
        int getChildCount();
        void addView(View child, int index);
        ... ...
}

接口的定义,在RecyclerView中:

this.mChildHelper = new ChildHelper(new ChildHelper.Callback() {
            public int getChildCount() {
                return RecyclerView.this.getChildCount();
            }

            public void addView(View child, int index) {
                RecyclerView.this.addView(child, index);
                RecyclerView.this.dispatchChildAttached(child);
            }

            public int indexOfChild(View view) {
                return RecyclerView.this.indexOfChild(view);
            }
        ... ...
        }

可见,Callback的具体实现,全是 调了RecyclerView 的方法。

ChildHelper 中的大部分方法,都按上面的逻辑来组织代码的:

  • 第一步:更新Bucket链 数据
  • 第二步:调用callback,调用RecyclerView 执行真正的操作.
  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洛克Lee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值