更新:目前已經寫了demo,歡迎討論:Android複雜資料流的“高效”渲染
我們知道Android中的ListView之所以可以實現item的無限載入,是因為對每個item的View 進行了快取複用。ListView的高效效能使得其在App開發中使用非常頻繁,本文主要分析在複雜資料展示時如何更加高效的使用ListView,如微博、facebook、twitter等的feed流需要展示非常多的資料型別:新聞、圖片、網頁連結、視訊,這種情況下ListView進行需要快取各種型別的View,App的記憶體佔用急劇升高……
ListView複用原理
1. 簡單列表複用
首先簡單介紹一下ListView的複用原理,我們知道使用ListView時一般需要結合Adapter使用,繼承BaseAdapter時,一般需要實現四個方法:
@Override
public int getCount() {
return 0;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return null;
}複製程式碼
其中getView是渲染每個Item時進行回撥生成View的,方法引數convertView就是ListView傳回可以複用的View,當其不為null時,無需重新建立View,可以直接使用convertView,進行資料渲染即可。其原理是當第一次呼叫時ListView直接將生成的View快取到一個ArrayList
2. 複雜列表複用
當列表中有多種型別的view時,我們需要實現BaseAdapter中的:
@Override
//返回view型別數量
public int getViewTypeCount() {
return super.getViewTypeCount();
}
@Override
//返回每個Item的型別
public int getItemViewType(int position) {
return super.getItemViewType(position);
}複製程式碼
這種情況下ListView實際為每種型別的Item設定了一個ArrayList進行快取:
複雜資訊流
此處以微博為例:
- 轉發帶視訊型別
- 普通文字+卡片型別
- 轉發圖文型別
此外還有原創圖文型別,原創視訊,原創卡片,系統通知,轉發視訊,轉發圖文,……,微博有多達二十種左右的item型別,每種型別中的View可能包括頭部圖片、文字描述、正文內容、正文圖片、正文視訊、分享操作欄等內容,這些都快取到記憶體中,再加上二十多種型別,想想記憶體的感受……
優化
我們可以看到很多型別中都有相同可以複用的部分,如頭部、分享操作欄等很多item中都是一樣,是否可單獨拿出來呢,我們進行簡單的拆分:
一個Item我們把它拆為來五個部分,首先頭部、評論操作欄等可以在很多不同型別的資料Item中進行復用,文字、圖片等的View也可以單獨進行復用,而且最重要的是:快取ArrayList中儲存的View數量將會減少,記憶體消耗減了不少。
具體實現中的坑
看到這裡,是不是很多同學覺得開啟了新世界的大門,急著進行程式碼的優化?具體的程式碼不方便貼出來,這裡說一下具體實現過程中碰到的坑:
- item click事件
由於優化的需求,把邏輯上的一個Item拆分為了多個item,因此每個item上都要設定ItemClick事件。具體實現時可以寫一個基類,在基類中對item click進行處理。 - cover 按壓效果
在item 點選時,一般需要有按壓效果,此時邏輯上的item已經進行了拆分,需要策略實現邏輯上item的整體按壓,而不是隻有某個拆分後的item被按壓。 - divider
我們知道listview的item之間是有divider的,此時需要設定divider為null,我們通過新增item的方式來實現divider效果。
效果
等填完拆分後的坑,執行程式,觀察前後的效果,記憶體佔用可以減少10~20m,滑動流暢度也提高不少,在低端手機上的效果尤其明顯,掉幀明顯減少。非常建議有需要的同學嘗試。
Other
歡迎關注公眾號wutongke,每天推送移動開發前沿技術文章: