Android——RecyclerView——Recycler类全部源码翻译及注释

总结一下:Recycler就是一个不折不扣的回收站,在里面针对ViewHolder进行一系列回收站应进行的操作。


下一个看adapter类或者rvpool类

 

// mAttachedScrap是你recycler类中当前维护的废品吗

final ArrayList<ViewHolder>mAttachedScrap = new ArrayList<>();

 

// mChangedScrap我猜测是将被遣送去重用的viewholder集合

ArrayList<ViewHolder> mChangedScrap =null;

 

//被缓存的views?

final ArrayList<ViewHolder> mCachedViews= new ArrayList<ViewHolder>();

 

// 把mAttachedScrap设置成只读(不可修改)的集合,牛

private final List<ViewHolder>

mUnmodifiableAttachedScrap =Collections.unmodifiableList(mAttachedScrap);

 

//把被请求的缓存最大值和view缓存最大值设为默认值2

private int mRequestedCacheMax = DEFAULT_CACHE_SIZE;

int mViewCacheMax = DEFAULT_CACHE_SIZE;

 

//维护一个RecycledViewPool的实例

RecycledViewPool mRecyclerPool;

 

//维护ViewCacheExtension的实例

private ViewCacheExtensionmViewCacheExtension;

 

static final int DEFAULT_CACHE_SIZE = 2;

 

//把报废的views从Recycler中清除出去,recyclerview pool中包含着的与recyclerview脱离联系的views将会被留存下来

public void clear() {

           mAttachedScrap.clear();

           recycleAndClearCachedViews();

       }

 

//设置被分离的、可用的views的最大数量,我们应该为了接下来的使用而保留的

public void setViewCacheSize(int viewCount){

           mRequestedCacheMax = viewCount;

           updateViewCacheSize();

       }

 

void updateViewCacheSize() {

            //更新缓存大小

           int extraCache = mLayout != null ? mLayout.mPrefetchMaxCountObserved :0;

           mViewCacheMax = mRequestedCacheMax + extraCache;

 

            //这里如果你更新了以后,发现已有的缓存比最大缓存数量大,那么就要把多余的部分回收掉。

           // first, try the views that can be recycled

           for (int i = mCachedViews.size() - 1;

                    i >= 0 &&mCachedViews.size() > mViewCacheMax; i--) {

                recycleCachedViewAt(i);

           }

       }

 

public List<ViewHolder>getScrapList() {

           return mUnmodifiableAttachedScrap;

       }

 

//验证ViewHolder的偏移位置(个人感觉神头鬼脸,看不太懂他想用这个方法干什么)

//是getViewForPosition的辅助方法

检查一个被给予的ViewHolder是否可以被用来作为被分享(共享)的位置

booleanvalidateViewHolderForOffsetPosition(ViewHolder holder) {

           // if it is a removed holder, nothing to verify since we cannot askadapter anymore

           // if it is not removed, verify the type and id.

            //如果这个holder已经被移除了,我们不能去校验它因为我们什么都不能询问Adapter了

            //如果这个holder没有被移除,校验这个holder的类型和id

           if (holder.isRemoved()) {

                if (DEBUG &&!mState.isPreLayout()) {

                    throw newIllegalStateException("should not receive a removed view unless it"

                            + " is prelayout");

                }

                return mState.isPreLayout();

           }

           if (holder.mPosition < 0 || holder.mPosition >=mAdapter.getItemCount()) {

                throw newIndexOutOfBoundsException("Inconsistency detected. Invalid view holder"

                        + "adapterposition" + holder);

           }

            //pre-layout到底是个啥概念?

           if (!mState.isPreLayout()) {

                // don't check type if it ispre-layout.

                final int type =mAdapter.getItemViewType(holder.mPosition);

                if (type !=holder.getItemViewType()) {

                   return false;

                }

           }

            //稳定的id,难道还有不稳定的id?要不要把这么简单的控件写的这么云里雾里?这还是优雅的写法吗?

           if (mAdapter.hasStableIds()) {

                return holder.getItemId() ==mAdapter.getItemId(holder.mPosition);

           }

           return true;

       }

 

//试图绑定视图,并考虑相关的时间信息.如果绑定视图的截止期限不等于FOREVER_NS,这个方法或许不能去绑定,并且会返回错误

private booleantryBindViewHolderByDeadline(ViewHolder holder, int offsetPosition,

                int position, long deadlineNs){

           //哦,不错,在这里把这个recyclerView赋给holder,昨天有看到过

           holder.mOwnerRecyclerView = RecyclerView.this;

           final int viewType = holder.getItemViewType();

           long startBindNs = getNanoTime();//获取java虚拟机中高精度的时间

           if (deadlineNs != FOREVER_NS

                    &&!mRecyclerPool.willBindInTime(viewType, startBindNs, deadlineNs)) {

                // abort(退出) - we have a deadline we can't meet

                return false;

           }

           //哦,不错,看到了熟悉的绑定方法,而且参数都是一样的

           mAdapter.bindViewHolder(holder, offsetPosition);

           long endBindNs = getNanoTime();

           //这里是把差值简单记录一下吗

           mRecyclerPool.factorInBindTime(holder.getItemViewType(), endBindNs -startBindNs);

            //连接可访问性代表?

           attachAccessibilityDelegate(holder.itemView);

           //这个prelayout还是没能理解

           if (mState.isPreLayout()) {

                holder.mPreLayoutPosition =position;

           }

           return true;

       }

 

//绑定所给的view到指定的位置,这个view可以是先前通过getViewForPosition(int)方法被检索的,或者是被Adapter#onCreateViewHolder(ViewGroup, int)方法创建的。大多数情况,一个LayoutManager应该通过getViewForPosition(int)方法来获取他的views并且让recyclerView来处理高速缓存。这是一个辅助方法用于一个想要去处理它自己的回收逻辑的LayoutManager。注意,getViewForPosition(int)方法已经绑定了view到这个位置上所以你不需要去调用这个方法除非你想要去绑定这个view到另一个位置。

public void bindViewToPosition(View view,int position) {

            //这个getchild让我,想不穿。

           ViewHolder holder = getChildViewHolderInt(view);

           if (holder == null) {

                throw newIllegalArgumentException("The view does not have a ViewHolder. Youcannot"

                        + " pass arbitraryviews to this method, they should be created by the "

                        + "Adapter");

           }

           //竟然还有AdapterHelper和ChildHelper这两个类,我tm。。还有光给一个位置怎么找偏移呢?

           final int offsetPosition = mAdapterHelper.findPositionOffset(position);

           if (offsetPosition < 0 || offsetPosition >=mAdapter.getItemCount()) {

                throw newIndexOutOfBoundsException("Inconsistency detected. Invalid item "

                        + "position "+ position + "(offset:" + offsetPosition + ")."

                        + "state:" +mState.getItemCount());

           }

            //看名字来说这个方法就是预处理一下?错了,就是在这个方法中发生了绑定

           tryBindViewHolderByDeadline(holder, offsetPosition, position,FOREVER_NS);

 

            //向下转型

           final ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();

           final LayoutParams rvLayoutParams;

           if (lp == null) {

                rvLayoutParams = (LayoutParams)generateDefaultLayoutParams();

               holder.itemView.setLayoutParams(rvLayoutParams);

            //如果这个参数未被检查(?)过

           } else if (!checkLayoutParams(lp)) {

                rvLayoutParams = (LayoutParams)generateLayoutParams(lp);

               holder.itemView.setLayoutParams(rvLayoutParams);

           } else {

                rvLayoutParams = (LayoutParams)lp;

           }

 

            //一开始我想,布局参数里还能维护这些实例的?神魔恋?一看,果然又是他自定义的布局参数类

            //设置成脏item(?)

            rvLayoutParams.mInsetsDirty = true;

            //把holder交给他去维护

           rvLayoutParams.mViewHolder = holder;

           //等待校验中

           rvLayoutParams.mPendingInvalidate = holder.itemView.getParent() == null;

       }

 

//转换预布局成布局后

//rv提供人工的位置范围在prelayout状态(终于领悟到了是还未布局的状态),并且自动的把这些位置映射到Adapter的位置当getViewForPosition(int)方法或者bindViewToPosition(View, int)被调用。通常,LayoutManager不需要去忧虑这个问题。然而,在某些情况下,你的LayoutManager或许需要去调用一些自定义组件,其中包含项目位置,在这种情况下你需要实际的Adapter的位置而不是prelayout的位置。你可以使用这个方法去转换一个prelayout的位置成Adapter的位置。注意如果被分享的位置属于一个被删除的ViewHolder,这个方法将会返回-1。调用这个方法在布局后状态将返回相同的值。

public intconvertPreLayoutPositionToPostLayout(int position) {

           if (position < 0 || position >= mState.getItemCount()) {

                throw newIndexOutOfBoundsException("invalid position " + position + ".State "

                        + "item count is" + mState.getItemCount());

           }

           if (!mState.isPreLayout()) {

                return position;

           }

           return mAdapterHelper.findPositionOffset(position);

       }

 

//获得为给定位置初始化的视图。这个方法应该被LayoutManager的实现类使用,并以此获得views去代表来自Adapter的数据。Recycler可能会重复使用一个报废的或者被脱离联系的View从一个被共享的pool中如果这个是可用的对于正确的view类型。如果适配器没有指出在给定位置的数据已经改变了,这个Recycler将会试图去返回之前为该数据初始化的废料视图,而不是重新绑定。

public View getViewForPosition(intposition) {

           return getViewForPosition(position, false);

       }

 

View getViewForPosition(int position,boolean dryRun) {

           return tryGetViewHolderForPositionByDeadline(position, dryRun,FOREVER_NS).itemView;

       }

 

//试图从给定的位置去获取ViewHolder,无论是从Recycler的废品,缓存,RecyclerViewPool或者直接的创建

如果在FOREVER_NS之外的截止日期被传递,那么这个方法会尽早返回而不是构建或绑定ViewHolder如果它不认为有这么宽裕的时间。如果必须构造一个ViewHolder并且没有足够的时间,将返回null,如果一个ViewHolder已经被获得&

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值