Android之ListView原理學習與最佳化總結

來源:互聯網
上載者:User

在整理前幾篇文章的時候有朋友提出寫一下ListView的效能最佳化方面的東西,這個問題也是小馬在面試過程中被別人問到的…..今天小馬就藉此機會來整理下,網上類似的資料蠻多的,倒不如自己寫一篇,記錄在這個地方,供自己以後使用,不用再翻來翻去的找了,用自己寫的…呵呵,不多講其它了,說起最佳化我想大家第一反應跟小馬一樣吧?想到利用ViewHolder來最佳化ListView資料載入,僅僅就此一條嗎?其實不是的,首先,想要最佳化ListView就得先瞭解ListView載入資料原理,這是前提,但是小馬在這個地方先做一些簡單的補充,大家一定仔細看下,保證會有收穫的:

列表的顯示需要三個元素:

根據列表的適配器類型,列表分為三種,ArrayAdapter,SimpleAdapter和SimpleCursorAdapter,這三種適配器的使用大家可學習下官網上面的使用或者自行百度Google,一堆DEMO!!!其中以ArrayAdapter最為簡單,只能展示一行字。SimpleAdapter有最好的擴充性,可以自訂出各種效果。SimpleCursorAdapter可以認為是SimpleAdapter對資料庫的簡單結合,可以方便的把資料庫的內容以列表的形式展示出來。

系統要繪製ListView了,他首先用getCount)函數得到要繪製的這個列表的長度,然後開始繪製第一行,怎麼繪製呢?調用getView()函數。在這個函數裡面首先獲得一個View這個看實際情況,如果是一個簡單的顯示則是View,如果是一個自訂的裡麵包含很多控制項的時候它其實是一個ViewGroup),然後再執行個體化並設定各個組件及其資料內容並顯示它。好了,繪製完這一行了。那 再繪製下一行,直到繪完為止,前面這些東西做下鋪墊,繼續…….

現在我們再來瞭解ListView載入資料的原理,有了這方面的瞭解後再說最佳化才行,下面先跟大家一起來看下ListView載入資料的基本原理小馬就直接寫了:

ListView的工作原理如下:

ListView 針對每個item,要求 adapter “返回一個視圖” (getView),也就是說ListView在開始繪製的時候,系統首先調用getCount)函數,根據他的傳回值得到ListView的長度,然後根據這個長度,調用getView)一行一行的繪製ListView的每一項。如果你的getCount)傳回值是0的話,列表一行都不會顯示,如果返回1,就只顯示一行。返回幾則顯示幾行。如果我們有幾千幾萬甚至更多的item要顯示怎麼辦?為每個Item建立一個新的View?不可能!!!實際上Android早已經緩衝了這些視圖,大家可以看下下面這個來理解下,這個圖是解釋ListView工作原理的最經典的圖了大家可以收藏下,不懂的時候拿來看看,加深理解,其實Android中有個叫做Recycler的構件,順帶列舉下與Recycler相關的已經由Google做過N多最佳化過的東東比如:AbsListView.RecyclerListener、ViewDebug.RecyclerTraceType等等,要瞭解的朋友自己查下,不難理解,是ListView載入資料的工作原理原理圖看不清楚的點擊後看大圖):

下面簡單說下的原理:

執行程式,查看日誌:

getView 被調用 9 次 ,convertView 對於所有的可見項目是空值如下):

然後稍微向下滾動List,直到item10出現:

      convertView仍然是空值,因為recycler中沒有視圖item1的邊緣仍然可見,在頂端)再滾動列表,繼續滾動:

     convertView不是空值了!item1離開螢幕到Recycler中去了,然後item11被建立,再滾動下:

此時的convertView非空了,在item11離開螢幕之後,它的視圖(…0f8)作為convertView容納item12了,好啦,結合以上原理,下面來看看今天最主要的話題,主角ListView的最佳化:

            首先,這個地方先記兩個ListView最佳化的一個小點:

                      1. ExpandableListView 與 ListActivity 由官方提供的,裡面要使用到的ListView是已經經過最佳化的ListView,如果大家的需求可以用Google內建的ListView滿足的的話盡量用官方的,絕對沒錯!

                      2.其次,像小馬前面講的,說ListView最佳化,其實並不是指其它的最佳化,就是記憶體是的最佳化,提到記憶體…想到OOM,折騰了我不少時間),很多很多,先來寫下,如果我們的ListView中的選項僅僅是一些簡單的TextView的話,就好辦啦,消耗不了多少的,但如果你的Item是自訂的Item的話,例如你的自訂Item布局ViewGroup中包含:按鈕、圖片、flash、CheckBox、RadioButton等一系列你能想到的控制項的話, 你要在getView中單單使用文章開頭提到的ViewHolder是遠遠不夠的,如果資料過多,載入的圖片過多過大,你BitmapFactory.decode的猛多的話,OOM搞死你,這個地方再警告下大家,是警告……….也提醒下自己:

                        小馬碰到的問題大家應該也都碰到過的,自訂的ListView項亂序問題,我很天真的在getView()中強制清除了下ListView的快取資料convertView,也就是convertView = null了,雖然當時是解決了這個問題讓其它每次重繪,但是犯了大錯了,如果資料太多的話,出現最最噁心的錯,手機卡死或強制關機,關機啊哥哥們……O_O,客戶殺了我都有可能,但大家以後別犯這樣的錯了,單單使用清除緩衝convertView是解決不了實際問題的,繼續……

下面是小記:圖片用完了正確的釋放… 


下面來列舉下真正意義上的最佳化吧:

好啦,ListVIew的最佳化問題,小馬就暫時先理解記錄這麼多了,如果朋友們有什麼更好的最佳化建議什麼的,留言指點下小馬,一定會及時添加到進來的,先謝謝啦,其實在ListView適配器的getView)方法中可以做很多的最佳化,我記得還有可以最佳化findViewById()這個方法來定址資源資訊效率的方法,資料太多了,小馬發現了會及時更新的哦,天太晚了,先休息了,吼吼,大家加油,一起努力學習!!!O_O

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.