原文:Android ListView複雜列表優化實踐 android
不少社交App都難免會涉及到複雜的列表元素實現,一個列表上面可能大量的圖片,不定長的評論列表,給手機端的程序員帶來了很多的挑戰。本文就是在實現複雜的列表滑動的狀況下,利用已知的優化方法指導下的一次優化實踐,旨在提高ListView的滑動流暢度,爲用戶帶來良好的體驗。 git
這是列表中可能出現的ItemView,有兩種,可是又有許多相同的地方,好比同樣有點讚的圖片,評論等...其中,評論和點讚的數量是可變的。 程序員
頭像表格:若是使用自帶的佈局LinearLayout和ImageView來完成,會致使佈局比較深,並且大量的addView操做會致使列表滑動的時候卡頓。 github
評論列表:和頭像表格同樣,因爲Item的數量是會變化的,會帶上和頭像表格一樣的問題。 canvas
大量圖片加載: 不難看出圖片的數量是可觀的,因爲每次請求回來的內容可能有不少條,若是數據一回來就請求裏面帶的所有圖片連接,即便使用了線程池,也會佔用cpu比較長的一段時間,所以也會帶來界面的不流暢問題。 緩存
(1): ViewHolder模式, 重用View和減小Child View查找時間,相信你們對這個都不陌生。 多線程
(2): 儘量減小布局層次 app
(3): 只刷新變化的部分View 佈局
(4): 避免調用addView這樣的方法 優化
(5): 只加載當前視圖須要的圖片,而且在滑動列表的時候中止後臺的加載線程,爲UI線程空出cpu資源,在中止的時候再請求。
(6): 首次加載圖片就處理(圓角/縮放等)並緩存在本地
把【頭像表格】和【評論列表】做爲一個總體的自定義View來實現,右邊的卡片結構基本一個RelativeLayout就能夠實現了,這樣整個Item就基本能夠控制在3~4個層次深度上面。
【頭像表格】實現注意點:
1):一開始應該先用默認頭像填充,以後再圖片返回的時候不要粗魯地使用invalidate(),而是使用invalidate(Rect rect),進行局部刷新,響應點擊事件更換背景時也應如此。
2):因爲onMesure和onDraw的的過程是比較頻繁和代價較高的,所以要儘量複用對象,如(Paint, Rect...)
【評論列表】實現要點:
1):除了上面提到的,這裏有個難點就是字符串的繪製,何時該換行?這裏涉及到很是複雜的文字處理,尤爲是不一樣國家的不一樣文字系統,幸虧,這些在Android API裏面都有了相關實現,筆者是在TextView中找到的,也就是android.text.Layout 的幾個實現類,筆者在這裏只是使用了DynamicLayout來實現。經過這個類你能夠得到字符串的高度信息(onMeasure),行數等...並且它已經實現了draw的過程,只需調整好畫布的位置(canvas.translate),直接調用就能夠了,很是方便。
【額外元素】
1):回到設計圖上,咱們看到還有可能出現的股票信息,對於這種額外元素,<ViewStub>最適合不過了...
【ListView】的數據變化:
1):對於整個Item的增長或者刪除動做,能夠調用notifyDataChanged()。
2):對於Item內部的數據變化,不要粗魯地使用notifyDataChanged(), 而是改變產生變化的View。
筆者一開始的想法是想作到:
1): 線程池,而且能夠暫停全部下載線程和恢復下載
2): 雙重緩存,本地永久緩存和內存級緩存
3): 滑動時候暫停全部下載,出讓cpu資源給UI線程。
在實現的過程當中,在多線程這裏常常作的很差,常常出問題,很是幸運在github上找到了一個開源項目能夠完美地解決上面的全部問題。如今咱們公司的Android項目全部的圖片加載已經自豪地使用上了... 附上地址:Android-Universal-Image-Loader
因爲筆者沒有保留以前的界面卡頓時候的代碼,所以只能演示最後的實現效果了,不能進行先後的比較。手機是小米4,圖表是Developer選項中的Profile GPU rendering中,打開後先後不斷滑動的結果。這裏能夠看到大部分狀況都能在綠線下,說明總體的體驗仍是很是流暢的。
喜歡炒股的朋友也能夠進一步去下載咱們的應用:微財 , 即將在3.0版本能夠體驗到。