Listview在Android中非常的重要,也非常的常見,我們在寫一些重型的數據顯示任務或者要在listview中加載一些圖片時候,就應該想到對其進行優化,同樣,在Android面試筆試的時候,這個問題也作爲一個十分常見的問題出現,我們現在來好好總結一下,從大的方面來說,優化listview主要可以從以下幾個方面入手。
*①Item佈局,層級越少越好,使用hierarchyview工具查看優化。
②複用convertView
③使用ViewHolder
④item中有圖片時,異步加載
⑤快速滑動時,不加載圖片
⑥item中有圖片時,應對圖片進行適當壓縮
⑦實現數據的分頁加載*
優化複用convertView ,就在MyAdapter類中的getView方法中,我們注意到,上面的寫法每次需要一個View對象時,都是去重新inflate一個View出來返回去,沒有實現View對象的複用,而實際上對於ListView而言,只需要保留能夠顯示的最大個數的view即可,其他新的view可以通過複用的方式使用消失的條目的view,而getView方法裏也提供了一個參數:convertView,這個就代表着可以複用的view對象,當然這個對象也可能爲空,當它爲空的時候,表示該條目view第一次創建,所以我們需要inflate一個view出來,所以在這裏,我們使用下面這種方式來重寫getView方法:
public View getView(int position, View convertView, ViewGroup parent) {
View view;
// 判斷convertView的狀態,來達到複用效果
if (null == convertView) {
//如果convertView爲空,則表示第一次顯示該條目,需要創建一個view
view = View.inflate(MainActivity.this, R.layout.listview_item,
null);
} else {
//否則表示可以複用convertView
view = convertView;
}
// listview_item裏只有一個textview
TextView tv_item = (TextView) view.findViewById(R.id.tv_item);
tv_item.setText(list.get(position));
return view;
}
上面是對view對象的複用做的優化,我們經過上面的優化之後,我們不需要每一個view都重新生成了。下面我們來解決下一個每一次都需要做的工作,那就是view中組件的查找:
TextView tv_item = (TextView) view.findViewById(R.id.tv_item);
實際上,findViewById是到xml文件中去查找對應的id,可以想象如果組件多的話也是挺費事的,如果我們可以讓view內的組件也隨着view的複用而複用,那該是多美好的一件事啊。。實際上谷歌也推薦了一種優化方法來做應對,那就是重新建一個內部靜態類,裏面的成員變量跟view中所包含的組件個數類型相同,我們這裏的view只包含了一個TextView,所以我們的這個靜態類如下:
private static class ViewHolder {
private TextView tvHolder;
}
那麼這個viewHolder類我們要如何使用纔可以達到複用效果呢?基本思路就是在convertView爲null的時候,我們不僅重新inflate出來一個view,並且還需要進行findviewbyId的查找工作,但是同時我們還需要獲取一個ViewHolder類的對象,並將findviewById的結果賦值給ViewHolder中對應的成員變量。最後將holder對象與該view對象“綁”在一塊。
當convertView不爲null時,我們讓view=converView,同時取出這個view對應的holder對象,就獲得了這個view對象中的TextView組件,它就是holder中的成員變量,這樣在複用的時候,我們就不需要再去findViewById了,只需要在最開始的時候進行數次查找工作就可以了。這裏的關鍵在於如何將view與holder對象進行綁定,那麼就需要用到兩個方法:setTag和getTag方法了:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
ViewHolder holder;
// 判斷convertView的狀態,來達到複用效果
if (null == convertView) {
// 如果convertView爲空,則表示第一次顯示該條目,需要創建一個view
view = View.inflate(MainActivity.this, R.layout.listview_item,
null);
//新建一個viewholder對象
holder = new ViewHolder();
//將findviewbyID的結果賦值給holder對應的成員變量
holder.tvHolder = (TextView) view.findViewById(R.id.tv_item);
// 將holder與view進行綁定
view.setTag(holder);
} else {
// 否則表示可以複用convertView
view = convertView;
holder = (ViewHolder) view.getTag();
}
// 直接操作holder中的成員變量即可,不需要每次都findViewById
holder.tvHolder.setText(list.get(position));
return view;
}
部分內容參考自:
這個博客