Android效能優化之Listview(ViewHolder重用機制)
好久沒發部落格了,因為發部落格太耗時間了,而且參考的比較多,也不想一直帶著轉載兩個字。都一直放在筆記裡。不過只能自己看不能和大家分享了,看到這篇文章令我恍然大悟,很有幫助,所以還是決定寫下來。
相信大家在很多時候都會用到ListView這個控制元件,因為確實是用的很多很多,但是有木有遇到過當資料很多很多的時候,往下滑ListView時有時候會卡頓,這就需要我們來優化它了。
ListView優化主要有下面幾個方面:
1、convertView重用
2、ViewHolder的子View複用
3、快取資料複用
一、convertView重用
首先講下ListView的原理:ListView中的每一個Item顯示都需要Adapter呼叫一次getView()的方法,這個方法會傳入一個convertView的引數,這個方法返回的View就是這個Item顯示的View。如果當Item的數量足夠大,再為每一個Item都建立一個View物件,必將佔用很多記憶體空間,即建立View物件(mInflater.inflate(R.layout.lv_item, null);從xml中生成View,這是屬於IO操作)是耗時操作,所以必將影響效能。Android提供了一個叫做Recycler(反覆迴圈)的構件,就是當ListView的Item從滾出螢幕視角之外,對應Item的View會被快取到Recycler中,相應的會從生成一個Item,而此時呼叫的getView中的convertView引數就是滾出螢幕的快取Item的View,所以說如果能重用這個convertView,就會大大改善效能。
那麼,我們怎麼重用它呢?貼程式碼:
如圖,當這個convertView不存在時,即第一次使用它,我們就建立一個item佈局的View物件並賦給convertView,以後使用convertView時,只需從convertView中getTag取出來就可以,不需要再次建立item的佈局物件了,這樣便提高了效能。
二、使用ViewHolder重用
我們都知道在getView()方法中的操作是這樣的:先從xml中建立view物件(inflate操作,我們採用了重用convertView方法優化),然後在這個view去findViewById,找到每一個item的子View的控制元件物件,如:ImageView、TextView等。這裡的findViewById操作是一個樹查詢過程,也是一個耗時的操作,所以這裡也需要優化,就是使用ViewHolder,把每一個item的子View控制元件物件都放在Holder中,當第一次建立convertView物件時,便把這些item的子View控制元件物件findViewById例項化出來並儲存到ViewHolder物件中。然後用convertView的setTag將viewHolder物件設定到Tag中, 當以後載入ListView的item時便可以直接從Tag中取出複用ViewHolder物件中的,不需要再findViewById找item的子控制元件物件了。這樣便大大提高了效能。
貼個完整的程式碼: