ListView原始碼分析,listview原始碼

來源:互聯網
上載者:User

ListView原始碼分析,listview原始碼
繼承關係


1、UML圖

圖中單獨畫出Scrollview是為了說明該ViewGroup並沒有內建回收機制,如果要是Scrollview顯示大量view,需要手動做處理。

 

2、繼承體系的分工

(1) AdapterView

An AdapterView is a view whose children aredetermined by an {@link Adapter}.

a.adapter相關的抽象函數:getAdapter、setAdapter

b.mEmptyView

c.觀察者模式

d. Accessibility:Android提供了Accessibility功能和服務協助這些使用者更加簡單地操作裝置,包括文字轉語音,觸覺反饋,手勢操作,軌跡球和手柄操作。

 

(2)AbsListView

Base class that can be used to implementvirtualized lists of items. A list does not have a spatial definition here. Forinstance, subclases of this class can display the content of the list in agrid, in a carousel, as stack, etc.

1.擁有RecycleBin類,負責處理view的產生和回收,沒有子視圖的空間定位資訊

2.滑動事件相關(touch orfling-based scrolling)

 

(3)ListView

A view that shows items in a verticallyscrolling list. The items come from the {@link ListAdapter} associated withthis view.

以垂直列表顯示資料,具體控制清單項目的排布和位移

Header和footer相關

3.優點:層次清晰,易於擴充

 

RecycleBin類(實現回收機制)


1.成員變數

(1)mFirstActivePosition

The position of the first view stored inmActiveViews.

儲存在mActiveViews中的第一個view的位置,即一個可視的子視圖

 

(2)mActiveViews

View[] 

Views that were on screen at the start oflayout. This array is populated at the start of layout, and at the end oflayout all view in mActiveViews are moved to mScrapViews. Views in mActiveViewsrepresent a contiguous range of Views, with position of the first view store in

mFirstActivePosition.

布局開始時螢幕顯示的view,這個數組會在布局開始時填充,布局結束後所有view被移至mScrapViews。

 

(3)mScrapViews

ArrayList<View>[]

Unsorted views that can be used by theadapter as a convert view.

可以被適配器用作convert view的無序view數組。這個ArrayList就是adapter中getView方法中的參數convertView的來源。注意:這裡是一個數組,因為如果adapter中資料有多種類型,那麼就會有多個ScrapViews。

 

2.成員函數

(1)shouldRecycleViewType

判斷給定的view的viewType指明是否可以回收回。

viewType < 0可以回收。指定忽略的(ITEM_VIEW_TYPE_IGNORE = -1),或者是 HeaderView / FootView(ITEM_VIEW_TYPE_HEADER_OR_FOOTER = -2)是不被回收的。如有特殊需要可以將自己定義的viewType設定為-1,否則,將會浪費記憶體,導致OOM。

 

(2) retrieveFromScrap

a.第三種情況,這個最簡單:

一開始,listview穩定後,此時mScrapView中是沒有緩衝view的,當我們向上滾動一小段距離(第一個此時仍顯示部分),新的view將會顯示,此時listview會調用Adapter.getView,但是緩衝中沒有,因此convertView是null,所以,我們得分配一塊記憶體來建立新的convertView;

 

b.第二種情況:

在a中,我們繼續向上滾動,直接第一個view完全移出螢幕(假設沒有新的item),此時,第一個view就會被detach,並被加入到mScrapView中;然後,我們還繼續向上滾動,直接後面又將要顯示新的item view時,此時,系統會從mScrapView中找position對應的View,顯然,是找不到的,則將從mScrapView中,取最後一個緩衝的view傳遞給convertView;

 

c.第一種情況:

AbsListView中的LayoutParams繼承了ViewGroup的LayoutParams,其中一個增加的成員變數是scrappedFromPosition,這個變數是由addScrapView時傳遞進來的position賦值,就是當時要回收的view的位置。所以scrappedFromPosition== position的判斷就是,如果某個位置的view被回收了,此時該位置又要重新顯示出來,那麼優先顯示原來的view,就是盡量保持原來位置的view不變。當然,如果原來的view已經用在別的位置了,那就沒辦法了。

 

(3) pruneScrapViews

確保mScrapViews的數目不會超過mActiveViews的數目 (This can happen if an adapter does not recycle its views)。mScrapView中每個ScrapView數組大小不應該超過mActiveView的大小,如果超過,系統認為程式並沒有複用convertView,而是每次都是建立一個新的view,為了避免產生大量的閑置記憶體且增加OOM的風險,系統會在每次回收後,去檢查一下,將超過的部分釋放掉,節約記憶體降低OOM風險。

 

產生新子視圖,即調用mAdapter.getView
1.private void scrollListItemsBy(int amount)

調用情景:按清單項目逐項移動,由onKeyDown、onKeyUp、onKeyMultiple調用

commonKey-->arrowScrollImpl-->arrowScrollImpl-->scrollListItemsBy

 

(1)初始化:

 

其中offsetChildrenTopAndBottom是將所有子視圖移動指定的像素:

最終調用mDisplayList的offsetTopBottom

 

(2)向上滑動的分支:


(3)

  

2.列表滑動產生清單項目視圖

(1)滑動時的呼叫堆疊

onTouchEvent (AbsListView)àscrollIfNeeded (AbsListView)

或者FlingRunnable (AbsListView)

à

trackMotionScroll (AbsListView)

à

fillGap

(在AbsListView中為抽象函數,在ListView中實現;向下調用fillDown,向上調用fillUp)

(在調用fillGap之前會調用offsetChildrenTopAndBottom)

à

 makeAndAddView (ListView)

沒有資料變化:從mRecycler中取得可視的view

資料有變化:obtainView-->setupChild

 

(2)重點分析:

1)obtainView:產生view,回收舊view和調用mApapter.getView的地方(AbsListView)

2)第一行的getScrapView最後調用第二部分分析RecycleBin類的retrieveFromScrap

 

3)setupChild:將view添加到viewgroup,對子視圖定位(ListView)

關鍵步驟:

a. attachViewToParent或者addViewInLayout

b. child.measure(childWidthSpec,childHeightSpec);

c. child.layout(childrenLeft, childTop,childRight, childBottom);

 

3. 再談回收

如果實現了RecyclerListener介面,當一個View由於ListView的滑動被系統回收到RecycleBin的mScrapViews數組時,會調用RecyclerListener中的onMovedToScrapHeap(View view)方法。RecycleBin相當於一個臨時儲存不需要顯示的那部分Views的對象,隨著列表滑動,這些Views需要顯示出來的時候,他們就被從RecycleBin中拿了出來,RecycleBin本身並不對mScrapViews中的對象做回收操作。

 

於是在工程裡,為ListView添加RecyclerListener介面,並在onMovedToScrapHeap方法中釋放ListItem包含的Bitmap資源,這樣可以極大的減少記憶體佔用。

 

關於RecyclerListener介面的注釋:

Sets the recycler listener to be notifiedwhenever a View is set aside in the recycler for later reuse. This listener canbe used to free resources associated to the View.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.