1.MeasureSpec的原理?
答:MeasureSpec封裝了從父級(jí)傳遞給子級(jí)的布局需求。每個(gè)MeasureSpec代表了寬度或高度的要求董济。MeasureSpec實(shí)現(xiàn)為32位的int,由size和mode組成,高2位代表mode,低30位代表size要门,通過(guò)將mode和size打包成一個(gè)int值來(lái)減少對(duì)象內(nèi)存分配虏肾,并提供打包和解包的方法。
MeasureSpec計(jì)算規(guī)則
2.ViewPager populate 源碼時(shí)序圖
首先 在ViewPager源碼中可以看到 populate 是在onMeasure中被調(diào)用欢搜,在Populate函數(shù)中可以看到
① mAdapter.startUpdate(this);
ViewPager開(kāi)始填充item封豪,調(diào)用startUpdate;
②填充可用寬度的3倍或不超過(guò)屏幕外的數(shù)量
③調(diào)用了addNewItem()來(lái)添加新的item
if (curItem == null && N > 0) {
//添加新的Item
curItem = addNewItem(mCurItem, curIndex);
}
在addNewItem方法中可以看到, 適配器負(fù)責(zé)將視圖添加到給定的容器中
mAdapter.instantiateItem(this, position)炒瘟。
④接著在Populate函數(shù)繼續(xù)往下看吹埠,會(huì)發(fā)現(xiàn)適配器調(diào)用了destroy
mAdapter.destroyItem(this, pos, ii.object);
銷(xiāo)毀item。
⑤calculatePageOffsets(curItem, curIndex, oldCurInfo);
計(jì)算頁(yè)面偏移量
⑥mAdapter.setPrimaryItem(this, mCurItem, curItem.object);
通知適配器當(dāng)前將哪個(gè)item顯示為當(dāng)前頁(yè)面
7?? mAdapter.finishUpdate(this); 結(jié)束更新
所以ViewPager無(wú)論存在多少個(gè)item疮装,都不會(huì)內(nèi)存溢出缘琅,一直在創(chuàng)建和銷(xiāo)毀。
使用ViewPager顯示輪播頁(yè)面廓推,默認(rèn)顯示當(dāng)前頁(yè)面刷袍,緩存左右兩個(gè)頁(yè)面,如果左右都有頁(yè)面樊展,往右滑動(dòng)呻纹,當(dāng)前頁(yè)面變?yōu)樽钭髠?cè)頁(yè)面,進(jìn)行緩存专缠,之前最左側(cè)頁(yè)面被銷(xiāo)毀雷酪,最右側(cè)頁(yè)面顯示為當(dāng)前頁(yè)面;如果往左滑動(dòng)涝婉,則相反之哥力。
如圖:
3.ViewPager + Fragment 緩存原理
由于ViewPager預(yù)加載緩存機(jī)制,每次緩存3個(gè)墩弯,如果之前有就不會(huì)重新創(chuàng)建省骂,也不會(huì)走其生命周期。
4.懶加載
懶加載的時(shí)機(jī):onCreateView()加載完畢最住,setUserVisibleHint()返回true钞澳,才可以進(jìn)行加載數(shù)據(jù)。
設(shè)置兩個(gè)bool 類(lèi)型變量涨缚,一個(gè)isFirstVisible轧粟,一個(gè)isFragmentVisible策治,在onActivityCreated()和setUserVisibleHint()處理,全部為true