先來點廢話
這周有點蛋疼,本來是打算前幾天就開始錄制相關視頻,編寫相關博客的,因為工作上的原因導致原本的計劃推遲了,很無奈。
周三領導突然叫我開會 ,我要與兩個同事弄個微信公眾號系統(包括后臺與前端)
領導:“下周你們要開始進入xxxx項目 大概 xxx時間完成 ,A與B我會叫他們和你一塊做”
我:“領導,你看時間是不是有點短,之前我們都沒有接觸過wx這塊,而且你看a同學又剛剛畢業,你看著 是不是得多預留些時間”
領導:“這個功能很簡單的啦,我相信你們” ;
我:“技術上可能問題不大,都比較有經驗,但你看涉及的系統 ERP,用戶系統、訂單系統什么的 就有6、7個,業務上是不是需要花個一周給我們培訓下”
領導:“邊做邊了解業務嘛”
我:**** “操你大爺,你行你來”(心里大吼,我慫)
領導:“這個功能很簡單,怎么實現我不管”
苦逼的開會,了解wx的公眾號 開發中心 各種信息,對接其他系統、碰需求,接口 ,開發計劃
上一節RecyclerView(3)- LayoutMagager源碼解析,LinearLayoutManager 大概了解了一些 layoutManager的一些方法,以及LinearLayoutManager的布局方式,這一節才是真正的recyclerView的核心,recycler復用機制。
通過本文你會知道
1、recylerView 存取view的一個流程
2、結合上一章RecyclerView(3)- LayoutMagager源碼解析,LinearLayoutManage你會感嘆 “哇 ,原來如此” 到 “哦,原來是這樣”
3、可以知道其中輔助類非常多,且很有意義,職責分離,重復代碼的一個優雅的封裝 、命名規范。
本文就不一步一步帶大家去看了,
先來一些基礎概念,也是分析過程當中的一些總結,看完之后 再去看源碼 會簡單輕松很多,然后在配合視頻來看 那最好不過了。
1、view: layoutPararms內保存了 viewHolder
2、viewHolder.mNestedRecyclerView保存了 復類 recyclerView
3、Recycler 內有幾個List<Holder> 作為緩存使用 分別是:mChangedScrap、mAttachedScrap、mCachedViews
且默認最大數量為2
4、ViewInfoStore保存了一些動畫信息
5、RecycledViewPool 內有 SparseArray<ScrapData>、viewType , 而SrapData內有 ArrayList<ViewHolder> mScrapHeap 且默認最大數量為5 也就是說每種viewType的的ViewHolder最多緩存5個。
回收得源碼大概是這樣的:
回收: recycler.recycleView(view);
ViewHolder holder = getChildViewHolderInt(view);
removeDetachedView(view, false);
if (holder.isScrap()) {
holder.unScrap();
} else if (holder.wasReturnedFromScrap()){
holder.clearReturnedFromScrapFlag();
}
recycleViewHolderInternal(holder);
getChildViewHolderInt
((LayoutParams) child.getLayoutParams()).mViewHolder;
removeDetachedView
dispatchChildDetached(child);
onChildDetachedFromWindow(child);
//暫時沒有做回收相關的動作
super.removeDetachedView(child, animate)
//如果有動畫 執行移除動畫 LayoutTransition.removeChild(this, child);
//移除焦點
dispatchViewRemoved(child);
onViewRemoved(child);
holder.unScrap();
從recycler的 廢料池mChangedScrap :list<ViewHodler> 中移除
或者 從recycler的 廢料池mAttachedScrap :list<ViewHodler> 中移除
viewHolder清除recycler的引用 清除標志;
holder.clearReturnedFromScrapFlag
清除標志
recycleViewHolderInternal
判斷cacheView內的數量 如果超過最大 那么 移除第一個
recycleCachedViewAt(0);
addViewHolderToRecycledViewPool(viewHolder, true);
clearNestedRecyclerViewIfNotNested(holder); //將viewHolder引用的recyclerView移除掉
dispatchViewRecycled(holder);
監聽移除、mViewInfoStore.removeViewHolder(holder);
getRecycledViewPool().putRecycledView(holder);
//加入廢料池
//從mCachedViews移除掉第0個
mCachedViews.add(targetCacheIndex, holder); //添加到合適的位置
mViewInfoStore.removeViewHolder(holder);
調用的簡化代碼在這里:
獲取: recycler.getViewForPosition(mCurrentPosition);
ViewHolder tryGetViewHolderForPositionByDeadline(int position,
boolean dryRun, long deadlineNs) {
//如果 mState.isPreLayout()
holder = getChangedScrapViewForPosition(position); //本質 mChangedScrap中獲取
//if (holder == null) {
holder = getScrapOrHiddenOrCachedHolderForPosition(position, dryRun); //本質 從 mAttachedScrap獲取 或者從 mCachedViews中獲取
//if (holder != null) {
if (!validateViewHolderForOffsetPosition(holder)) {
//從緩存當中移除view
//if (holder == null && mViewCacheExtension != null)
final View view = mViewCacheExtension
.getViewForPositionAndType(this, position, type);
// 通過view 拿到viewHolder
//if (holder == null) { // fallback to pool
holder = getRecycledViewPool().getRecycledView(type);
if (holder != null) {
` holder.resetInternal();
// if (holder == null) {
holder = mAdapter.createViewHolder(RecyclerView.this, type);
從adapter內取出 holder 將 recyclerVIew的引用 設置進viewHoler
//初始化 viewType廢料列表與記錄 oncreateViewHoler的一個時間 mRecyclerPool.factorInCreateTime(type, end - start);
viewholer.mPreLayoutPosition =postion;
測量layoutParams
return viewHolder;
總結起來是這樣的
本文從 view的獲取與銷毀為切入點出發,來過了一遍 淺顯的解析了一遍 view的回收、復用的過程。
詳細請看:
文章視頻地址:鏈接:http://pan.baidu.com/s/1hssvXC4 密碼:18v1
· RecyclerView(1)- Decoration源碼解析
· RecyclerView(2)- 自定義Decoration打造時光軸效果
· RecyclerView(3)- LayoutMagager源碼解析,LinearLayoutManager
· RecyclerView(4)- 核心、Recycler復用機制_1
· RecyclerView(4)- 核心、Recycler復用機制_2
· RecyclerView(5)- 自定義LayoutManager(布局、復用)
· RecyclerView(6)- 自定義ItemAnimator
· RecyclerView(7)- ItemTouchHelper
· RecyclerView(8)- MultiTypeAdapter文章、MultiTypeAdapter Github地址
希望我的文章不會誤導在觀看的你,如果有異議的地方歡迎討論和指正。
如果能給觀看的你帶來收獲,那就是最好不過了。