ViewPager系列文章(一)- ViewPager源碼分析及加載頁(yè)面原理圖

1. ViewPager源碼分析

1>:點(diǎn)擊 viewPager.setAdapter進(jìn)入下邊源碼,會(huì)調(diào)用 populate() 方法,這個(gè)方法作用是創(chuàng)建和銷毀子條目(子item):

/**
     * Set a PagerAdapter that will supply views for this pager as needed.
     *
     * @param adapter Adapter to use
     */
    public void setAdapter(PagerAdapter adapter) {
         populate();
    }
void populate(int newCurrentItem) {
        if (curItem == null && N > 0) {
            // 創(chuàng)建item
            curItem = addNewItem(mCurItem, curIndex);
        }
       if (pos == ii.position && !ii.scrolling) {
             // 銷毀item
            mAdapter.destroyItem(this, pos, ii.object);              
    }
    private static final int DEFAULT_OFFSCREEN_PAGES = 1;
    public void setOffscreenPageLimit(int limit) {
        if (limit < DEFAULT_OFFSCREEN_PAGES) {
            Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " +
                    DEFAULT_OFFSCREEN_PAGES);
            limit = DEFAULT_OFFSCREEN_PAGES;
        }
        if (limit != mOffscreenPageLimit) {
            mOffscreenPageLimit = limit;
            populate();
        }
    }

在populate()方法中:
創(chuàng)建ItemView:mAdapter.instantiateItem(this, position);
銷毀ItemView:mAdapter.destroyItem(this, pos, ii.object);
所以由ViewPager的源碼可以看出,ViewPager里邊無(wú)論放多少個(gè)頁(yè)面都不會(huì)內(nèi)存溢出,它會(huì)不斷的去創(chuàng)建和銷毀view;

和 ListView、RecyclerView不一樣,ListView、RecyclerView是會(huì)不斷的復(fù)用view,而viewpager是不斷的創(chuàng)建和銷毀view

2. ViewPager加載頁(yè)面的原理如圖所示:

ViePager加載頁(yè)面的原理.png

輪播圖剛打開默認(rèn)顯示當(dāng)前頁(yè),是第一頁(yè),默認(rèn)會(huì)緩存左右兩個(gè)頁(yè)面,如果左邊沒(méi)有,只有右邊有,那么右邊是第0頁(yè),當(dāng)前頁(yè)是第一頁(yè);
如果你滑動(dòng)到第1頁(yè),ViewPager會(huì)默認(rèn)把 左邊第0頁(yè) 和 右邊第2頁(yè) 創(chuàng)建出來(lái);
如果你滑動(dòng)到第2頁(yè),ViewPager會(huì)默認(rèn)把第1頁(yè)和第3頁(yè)創(chuàng)建出來(lái),而原來(lái)的第0頁(yè)就會(huì)變成需要銷毀的頁(yè)面;

如果想要緩存多頁(yè),可以調(diào)用setOffscreenPageLimit()方法:
setOffscreenPageLimit(1):ViewPager機(jī)制默認(rèn)就是緩存1,表示左邊、右邊各緩存1頁(yè),加上自己,總共是3頁(yè),其余頁(yè)面全部銷毀;
setOffscreenPageLimit(2):表示默認(rèn)給左右各緩存2頁(yè),共4頁(yè),加上自己,總共緩存5頁(yè),其余頁(yè)面全部銷毀;
setOffscreenPageLimit(3):表示默認(rèn)給左右各緩存3頁(yè),共6頁(yè),加上自己,總共緩存7頁(yè),其余頁(yè)面全部銷毀;

3. 總結(jié):

1>:ViewPager真正的子View只是兩邊 "緩存" 的頁(yè)面+1(當(dāng)前顯示頁(yè)面),那么ViewPager如何做到從頭滑動(dòng)到尾不出問(wèn)題呢?

因?yàn)?smoothScrollTo()滑動(dòng)方法也調(diào)用populate(),而populate()方法維護(hù)了當(dāng)前顯示頁(yè)面和 左右緩存的頁(yè)面,就能做到無(wú)限滑動(dòng)而不出問(wèn)題;

2>:populate()如何讓 ViewPager的子View 一直保持為 兩邊"緩存"頁(yè)面 + 當(dāng)前頁(yè)面?

A:從populate()源碼中可知:先判斷頁(yè)面是否在緩存范圍內(nèi):如果在,則addNewItem添加進(jìn)來(lái),否則在destroyItem掉;
B:ViewPager會(huì)緩存左右兩邊頁(yè)面+1(當(dāng)前顯示頁(yè)面),默認(rèn)認(rèn)為當(dāng)前頁(yè)面的 左右兩邊各有1個(gè),用戶可以手動(dòng)調(diào)用setOffscreenPageLimit()方法設(shè)置數(shù)量,如果傳的值小于1,就默認(rèn)設(shè)置為1;
ViewPager實(shí)際示意圖如下:


ViewPager實(shí)際示意圖.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,941評(píng)論 25 709
  • 兒子,你的十二年寒窗終于走到盡頭了,明天,你將會(huì)和近干萬(wàn)的高三學(xué)子一起走向人生第一個(gè)重大的戰(zhàn)場(chǎng)。而此時(shí),竟然有諸多...
    沙漠里的夕陽(yáng)閱讀 257評(píng)論 0 1
  • 人生不如意,十之八九。olabuy想說(shuō),不管是生活上,還是在工作上,我們總會(huì)遇到各種各樣不順心的事情,這時(shí)候難免會(huì)...
    情比金堅(jiān)閱讀 226評(píng)論 0 0
  • 張三豐是一只和我很有緣份的貓,但是他喜歡的人不是它它我。 那時(shí),我有個(gè)店。 1 接近年關(guān)了,張三豐的主人又把張三豐...
    千米學(xué)路閱讀 776評(píng)論 1 1
  • 鮮花一團(tuán)團(tuán)一簇簇?cái)D偎在一起 蝶蜂翩翩起舞成群結(jié)隊(duì)來(lái)來(lái)去去 很美的季節(jié) 就是身邊少了你 蓮花綻開清香四溢陣陣沁人心脾...
    柳青桐閱讀 298評(píng)論 6 3

友情鏈接更多精彩內(nèi)容