RecyclerView(4)- 核心源碼解析、Recycler復用機制

先來點廢話
這周有點蛋疼,本來是打算前幾天就開始錄制相關視頻,編寫相關博客的,因為工作上的原因導致原本的計劃推遲了,很無奈。
周三領導突然叫我開會 ,我要與兩個同事弄個微信公眾號系統(包括后臺與前端)

領導:“下周你們要開始進入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地址


希望我的文章不會誤導在觀看的你,如果有異議的地方歡迎討論和指正。
如果能給觀看的你帶來收獲,那就是最好不過了。

人生得意須盡歡, 桃花塢里桃花庵
點個關注唄,對,不信你點試試?
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,406評論 6 538
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,034評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,413評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,449評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,165評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,559評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,606評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,781評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,327評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,084評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,278評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,849評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,495評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,927評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,172評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,010評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,241評論 2 375

推薦閱讀更多精彩內容

  • 本篇文章已授權微信公眾號 guolin_blog (郭霖)獨家發布 最近在研究 RecyclerView 的回收復...
    請叫我大蘇閱讀 15,551評論 40 138
  • 這篇文章分三個部分,簡單跟大家講一下 RecyclerView 的常用方法與奇葩用法;工作原理與ListView比...
    LucasAdam閱讀 4,410評論 0 27
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,692評論 25 708
  • 能力就是會把一個問題拆解為一個個小問題,然后針對小問題進行解決,有些是自己能解決的,如果有不能解決的,也能知道找到...
    羅菱閱讀 231評論 0 0
  • 李健的歌初聽給人的印象就是安靜,空靈。他的歌與那種極富個性與節奏的歌曲形成鮮明的對比,其歌曲伴奏有時體現出濃濃的俄...
    AnriquejoanChou閱讀 816評論 0 0