Android RecyclerView 局部刷新分析

onAttachedToRecyclerView

notifyItemChange notifyItemRemove

notifyDataChange

ViewHolder

RecyclerViewDataObserver

onBindViewHolder      notifyItemRangeChanged

onItemRangeChanged positionStart itemCount ,payload

mIsAttached
AdapterHelper
triggerUpdateProcessor        requestLayout


setAdapter
setAdapterInternal
         adapter.onAttachedToRecyclerView(this);RecyclerView
 mTestAdapter.notifyItemChanged(3);

 RecyclerView
    public final void notifyItemChanged(int position) {
            mObservable.notifyItemRangeChanged(position, 1);
        }

 notifyItemRangeChanged(positionStart, itemCount, null);
         for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onItemRangeChanged(positionStart, itemCount, payload);
            }

public static abstract class AdapterDataObserver {
        public void onChanged() {
            // Do nothing
        }

        public void onItemRangeChanged(int positionStart, int itemCount) {
            // do nothing
        }

        public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
            // fallback to onItemRangeChanged(positionStart, itemCount) if app
            // does not override this method.
            onItemRangeChanged(positionStart, itemCount);
        }

        public void onItemRangeInserted(int positionStart, int itemCount) {
            // do nothing
        }

        public void onItemRangeRemoved(int positionStart, int itemCount) {
            // do nothing
        }

        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
            // do nothing
        }
    }
AdapterDataObserver        RecyclerViewDataObserver


RecyclerView
    private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();

    private class RecyclerViewDataObserver extends AdapterDataObserver {


onItemRangeChanged    triggerUpdateProcessor     requestLayout

    boolean onItemRangeChanged(int positionStart, int itemCount, Object payload) {
        mPendingUpdates.add(obtainUpdateOp(UpdateOp.UPDATE, positionStart, itemCount, payload));
        mExistingUpdateTypes |= UpdateOp.UPDATE;
        return mPendingUpdates.size() == 1;
    }
size == 1时才 requestLayout,第一次时  onItemRangeChanged时才 requestLayout

    final ArrayList<UpdateOp> mPendingUpdates = new ArrayList<UpdateOp>();

notifyItemChange  ViewHolder     动画效果xiao

局部刷新
oldHolder newHolder 

scrapView

  // 如果不需要更新 放到 mAttachedScrap 中
    if (holder.hasAnyOfTheFlags(ViewHolder.FLAG_REMOVED | ViewHolder.FLAG_INVALID)
        // 没有更新 或者 可以被复用
            || !holder.isUpdated() || canReuseUpdatedViewHolder(holder)) {
        ...
        holder.setScrapContainer(this, false);
        mAttachedScrap.add(holder);
    } else {
         // 需要更新 放到 mChangedScrap 中
        if (mChangedScrap == null) {
            mChangedScrap = new ArrayList<ViewHolder>();
        }
        holder.setScrapContainer(this, true);
        mChangedScrap.add(holder);
        
        canReuseUpdatedViewHolder
        
        
           void scrapView(View view) {
            final ViewHolder holder = getChildViewHolderInt(view);
            holder.setScrapContainer(this);
            if (!holder.isChanged() || !supportsChangeAnimations()) {
                if (holder.isInvalid() && !holder.isRemoved() && !mAdapter.hasStableIds()) {
                    throw new IllegalArgumentException("Called scrap view with an invalid view."
                            + " Invalid views cannot be reused from scrap, they should rebound from"
                            + " recycler pool.");
                }
                mAttachedScrap.add(holder);
            } else {
                if (mChangedScrap == null) {
                    mChangedScrap = new ArrayList<ViewHolder>();
                }
                mChangedScrap.add(holder);
            }
        }
        
        notifyItemChange requestLayout bindViewHolder

 

 

 

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    dispatchLayout();
    mFirstLayoutComplete = true;
}

    //2.mInPreLayout 设置为 true 后面有用
    mState.mInPreLayout = mState.mRunPredictiveAnimations;

  //5.保存动画信息相关
            mViewInfoStore.addToPreLayout(holder, animationInfo);
            
            
              //3.如果holder确定要更新,就把它添加到 oldChangeHolders 集合中
                long key = getChangedHolderKey(holder);
               mViewInfoStore.addToOldChangeHolders(key, holder);  


               @VisibleForTesting
    final LongSparseArray<RecyclerView.ViewHolder> mOldChangedHolders = new LongSparseArray<>();
    
           public void onLayoutChildren(Recycler recycler, State state) {
            Log.e(TAG, "You must override onLayoutChildren(Recycler recycler, State state) ");
        }
        
        
            private void processAdapterUpdatesAndSetAnimationFlags() {
            
               // 通常情况就是 ture
    mState.mRunSimpleAnimations = true
    
     // 通常情况就是 ture
    mState.mRunPredictiveAnimations = true
    
       mAdapterHelper.preProcess();
    
        for (int i = 0; i < count; i++) {
            UpdateOp op = mPendingUpdates.get(i);
               case UpdateOp.UPDATE:
                    applyUpdate(op);
                    break;
                    
                    UpdateOp newOp = obtainUpdateOp(UpdateOp.UPDATE, tmpStart, tmpCount,
                            op.payload);
                    postponeAndUpdateViewHolders(newOp);

     case UpdateOp.UPDATE:
                mCallback.markViewHoldersUpdated(op.positionStart, op.itemCount, op.payload);
                break;
                    
                    
                  void initAdapterManager() {
        mAdapterHelper = new AdapterHelper(new AdapterHelper.Callback() {


           @Override
            public void markViewHoldersUpdated(int positionStart, int itemCount, Object payload) {
                viewRangeUpdate(positionStart, itemCount, payload);
                mItemsChanged = true;
            }

void viewRangeUpdate(int positionStart, int itemCount, Object payload) {
        final int childCount = mChildHelper.getUnfilteredChildCount();
        final int positionEnd = positionStart + itemCount;


   if (holder.mPosition >= positionStart && holder.mPosition < positionEnd) {
                // We re-bind these view holders after pre-processing is complete so that
                // ViewHolders have their final positions assigned.
                holder.addFlags(ViewHolder.FLAG_UPDATE);
                holder.addChangePayload(payload);
                // lp cannot be null since we get ViewHolder from it.
                ((LayoutParams) child.getLayoutParams()).mInsetsDirty = true;
            }

        processAdapterUpdatesAndSetAnimationFlags();
        
        
           if (mState.mTrackOldChangeHolders && holder.isUpdated() && !holder.isRemoved()
                        && !holder.shouldIgnore() && !holder.isInvalid()) {
                    long key = getChangedHolderKey(holder);
                    // This is NOT the only place where a ViewHolder is added to old change holders
                    // list. There is another case where:
                    //    * A VH is currently hidden but not deleted
                    //    * The hidden item is changed in the adapter
                    //    * Layout manager decides to layout the item in the pre-Layout pass (step1)
                    // When this case is detected, RV will un-hide that view and add to the old
                    // change holders list.
                    mViewInfoStore.addToOldChangeHolders(key, holder);
                }
        
            @VisibleForTesting
    final LongSparseArray<RecyclerView.ViewHolder> mOldChangedHolders = new LongSparseArray<>();
    
    
        //4.很重要,LayoutManager 开始工作
    mLayout.onLayoutChildren(mRecycler, mState);
    
     for (int i = childCount - 1; i >= 0; i--) {
                final View v = getChildAt(i);
                scrapOrRecycleView(recycler, i, v);
            }
            
            
                    return ((LayoutParams) child.getLayoutParams()).mViewHolder;
            
       recycler.scrapView(view);
       
       不更新
            mAttachedScrap.add(holder);
       
        public final class Recycler {
        final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
        
        
        更新的话
           mChangedScrap.add(holder);
                ArrayList<ViewHolder> mChangedScrap = null;
                
                  ViewHolder tryGetViewHolderForPositionByDeadline(int position,
                boolean dryRun, long deadlineNs) {
                
                 if (mState.isPreLayout()) {
        holder = getChangedScrapViewForPosition(position);
        
        
                final ViewHolder holder = mChangedScrap.get(i);
        
        
        
              holder = getScrapOrHiddenOrCachedHolderForPosition(position, dryRun);
        
        
                final ViewHolder holder = mAttachedScrap.get(i);
                
                Recycler
                     final ViewHolder holder = mCachedViews.get(i);
                     
                             final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();
                     
        
        
          final int offsetPosition = mAdapterHelper.findPositionOffset(position);
        ...
        final int type = mAdapter.getItemViewType(offsetPosition);
        
        
        
                    final View view = mViewCacheExtension
                    .getViewForPositionAndType(this, position, type);
                    
                        //4. 从 RecycledViewPool 中查找
            holder = getRecycledViewPool().getRecycledView(type);
            ...
            
               //5. 老实创建
            holder = mAdapter.createViewHolder(RecyclerView.this, type);
            ...
            
            
            dispatchLayoutStep2
            
            
            
        // Step 2: Run layout
        mState.mInPreLayout = false;
        mLayout.onLayoutChildren(mRecycler, mState);

            
            

ActiveViews和mAttachedScrap功能相似

mScrapVIew和mCachedViews    + mRecyclerPool|否|是|与自身生命周期一致


makeAndAddView     


mActiveViews|否|否|onLayout函数周期内|用于屏幕内itemView快速重用| 

listview
makeAndAddView


    mScrapVIew和mCachedViews
    
    mAdapter .getView 
    createView , view
    
    
    RecyclerView
    getViewForPosition
    
    mAttachedScrap|否|否|onLayout函数周期内|用于屏幕内itemView快速重用|
    
    
    mCacheViews的使用
    
    mViewCacheExtension||||不直接使用
    
    
    mRecyclerPool|否|是|与自身生命周期一致
    
    
    mAdapter.createViewHolder
    
    
    mAdapter.binderViewHolder
    
    
    


    public void setAdapter(ListAdapter adapter) {
        if (mAdapter != null) {
            mAdapter.unregisterDataSetObserver(mObserver);
        }

   if (adapter != null) {
            adapter.registerDataSetObserver(mObserver);
            mRecycler.setViewTypeCount(adapter.getViewTypeCount());
            mHasStableIds = adapter.hasStableIds();
        } else {
            mHasStableIds = false;
        }
        populate();

   layoutChildren(mDataChanged);

             View newView = obtainView(position, child);


  view = mAdapter.getView(position, scrap, this);

        if (view != scrap && scrap != null) {
            // The adapter didn't use it; put it back.
            mRecycler.addScrap(scrap);
        }


    View getView(int position, View convertView, ViewGroup parent);


    private class RecycleBin {
        private ArrayList<View>[] mScrapViews;


  ArrayList<View>[] scrapViews = new ArrayList[viewTypeCount];
            for (int i = 0; i < viewTypeCount; i++) {
                scrapViews[i] = new ArrayList<View>();
            }


            onLayout
            
@Override
    protected void layoutChildren() {
            
            
                    // Flush any cached views that did not get reused above
            recycleBin.scrapActiveViews();    
            
            
                 if (hasListener) {
                            mRecyclerListener.onMovedToScrapHeap(victim);
                        }
            
            layoutChildren
            
            RecycleBin
            
            
            addScrapView changed
            
            fillActiveViews no changed
            
            
              // Clear out old views
            detachAllViewsFromParent();        
            
            makeAndAddView        
            
             if (params.viewType == mAdapter.getItemViewType(position)) {
                final View updatedView = mAdapter.getView(position, transientView, this);

mAdapter.getView                  
            
detachViewFromParent
            
            
            layoutChildren fillFromTop
            
            fillDown
            
            makeAndAddView
            
            setupChild
            
        attachViewToParent    
            
            
    getItemViewType getViewTypeCount        
            
            
            addViewAbove addViewBelow
            
            
    mActiveViews 一级缓存
mScrapViews 二级缓存    
            
    mActiveViews ,mAtta        

            
            

Recycler

scrapList          mAttachedScrap mChangedScrap mCacheViews RecycledViewPool


tryGetViewHolderForPositionByDeadline


onBindViewHolder


detachAndScrapAttachedViews

      vh.addFlags(ViewHolder.FLAG_TMP_DETACHED);

FLAG_TMP_DETACHED

   recycleByLayoutState(recycler, layoutState); //根据滚动的距离来回收Viewvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
   
    void recycleViewHolderInternal(ViewHolder holder) {


 void recycleViewHolderInternal(ViewHolder holder) {

 
 
      void recycleCachedViewAt(int cachedViewIndex) {
            if (DEBUG) {
                Log.d(TAG, "Recycling cached view at index " + cachedViewIndex);
            }
            ViewHolder viewHolder = mCachedViews.get(cachedViewIndex);
            if (DEBUG) {
                Log.d(TAG, "CachedViewHolder to be recycled: " + viewHolder);
            }
            addViewHolderToRecycledViewPool(viewHolder, true);
            mCachedViews.remove(cachedViewIndex);
        }
        
        mCacheViews        recycleCachedViewAt
        
        
                    addViewHolderToRecycledViewPool(viewHolder, true);
            mCachedViews.remove(cachedViewIndex);
            
            
              getRecycledViewPool().putRecycledView(holder);
              
              RecycledViewPool
              
              
              
                 mCachedViews.add(targetCacheIndex, holder);
                 
                 createViewHolder
                 bindViewHolder
                 

  

child.getLayoutParams

child.getLeft         params.leftMargin

RecycleView.LayoutManager      


StaggeredGridLayoutManager 瀑布就式布局管理器

getItemOffsets


onBindViewHolder

holder.sg_item.getLayoutParams
layoutParams.height = heights.get position

ItemTouchHelper attachToRecyclerView
 

         
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
                    
                    

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值