RecyclerView,Android自学资料

本文详细探讨了RecyclerView的滚动实现,重点分析了LinearLayoutManager下的smoothScrollToPosition方法。通过跟随源码,揭示了LinearSmoothScroller、RecyclerView.SmoothScroller、Scroller等组件在滑动过程中的作用。在滚动过程中,涉及到ViewFlinger的postOnAnimation()和run()方法,以及计算滚动时间和速度的过程。整个流程解释了RecyclerView如何高效地进行平滑滚动。
摘要由CSDN通过智能技术生成

到了这里我们发现对于不同情况,RecyclerView内部处理是不一样的,所以为了解决实际问题,看源码是必不可少的,接下来我们就一起跟着源码走一遍。来看看RecyclerView具体的滚动实现。(这里需要提醒大家的是这里我采用的是LinearLayoutManager,本文章都是基于LinearLayoutManager进行分析的)

 public void smoothScrollToPosition(int position) {
        if (mLayoutFrozen) {
            return;
        }
        if (mLayout == null) {
            Log.e(TAG, "Cannot smooth scroll without a LayoutManager set. "
                    + "Call setLayoutManager with a non-null argument.");
            return;
        }
        mLayout.smoothScrollToPosition(this, mState, position);
    } 

mRecycler.smoothScrollToPosition()方法时,内部调用了LayoutManager的smoothScrollToPosition方法,LayoutManager中smoothScrollToPosition没有实现,具体实现在其子类中,这里我们使用的是LinearLayoutManager,所以我们来看看内部是怎么实现的。

 @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
            int position) {
        LinearSmoothScroller scroller = new LinearSmoothScroller(recyclerView.getContext());
        scroller.setTargetPosition(position);//设定目标位置
        startSmoothScroll(scroller);
    } 

这里我们可以看到,这里导致RecyclerView滑动的是LinearSmoothScroller,而LinearSmoothScroller的父类是RecyclerView.SmoothScroller,看到这里我相信大家都会感到一丝熟悉,因为我们在对控件内内容进行移动的时候,我们都会使用到一个类,那就是Scroller。这里RecyclerView也自定了一个滑动Scroller。肯定是与滑动其内部视图相关的。

 public void startSmoothScroll(SmoothScroller smoothScroller) {
            if (mSmoothScroller != null && smoothScroller != mSmoothScroller
                    && mSmoothScroller.isRunning()) {
                mSmoothScroller.stop();
            }
            mSmoothScroller = smoothScroller;
            mSmoothScroller.start(mRecyclerView, this);
        } 

继续走startSmoothScroll,方法内部判断了如果正在计算坐标值就停止,然后调用start()方法重新开始计算坐标值。接着开始看start()方法。

 void start(RecyclerView recyclerView, LayoutManager layoutManager) {
            mRecyclerView = recyclerView;
            mLayoutManager = layoutManager;
            if (mTargetPosition == RecyclerView.NO_POSITION) {
                throw new IllegalArgumentException("Invalid target position");
            }
            mRecyclerView.mState.mTargetPosition = mTargetPosition;
            mRunning = true;//设置当前scroller已经开始执行
            mPendingInitialRun = true;
            mTargetView = findViewByPosition(getTargetPosition());//根据目标位置查找相应View,
            onStart();
            mRecyclerView.mViewFlinger.postOnAnimation();
        } 

在start方法中,会标识当前scroller的执行状态,同时会根据滚动的位置去寻找对应的目标视图。这里需要着重提示一下,findViewByPosition()这个方法,该方法会在Recycler的可见范围内去查询是否有目标位置对应的视图,例如,现在RecyclerView的可见范围为1-9,目标位置为10,那么mTargetView =null,如果可见范围为9-20,目标位置为1,那么mTargetView =null。

最终调用RecyclerView的内部类 ViewFlinger的postOnAnimation()方法。

 class ViewFlinger implements Runnable {
	   ....省略部分代码
     void postOnAnimation() {
            if (mEatRunOnAnimationRequest) {
                mReSchedulePostAnimationCallback = true;
            } else {
                removeCallbacks(this);
   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值