Android內建的ListView只能滿足初步的列表顯示需求。
如果想要在清單項目中添加圖片等控制項,就需要一個適配器(Adapter)。
此時需要重寫Adapter的getView方法,這個方法是整個列表的主要計算消耗。
寫得不好會影響列表的效能,而且往往會成為效能瓶頸。
</pre><p style="font-size:13px; line-height:1.4; margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; font-family:Verdana,Geneva,Arial,Helvetica,sans-serif"></p><pre name="code" class="java">private LayoutInflater mInflater =
(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
public View getView(int position, View convertView, ViewGroup parent) {
convertView = mInflater.inflate(R.layout.list_item_icon_text, null);
TextView text = (TextView) convertView.findViewById(R.id.text);
ImageView icon = (ImageView) convertView.findViewById(R.id.icon);
text.setText(textData[position]);
icon.setImageBitmap(iconData[position]);
return convertView;
}
如以上代碼所示,列表需要展現清單項目的時候,就會調用getView方法。
其中position就是清單項目的位置,convertView為清單項目當前使用的視圖對象。
開發人員只需根據position來決定如何填充一個視圖,並返回給適配器就行了。
以上代碼重用了清單項目中的視圖對象,但是這樣做效能還是很差。
效能提升:
Google I/O大會上給出的方案,確實能提升效能。
將方法中調用findViewById得到的控制項對象存起來,
避免每次建立新視圖對象時都要調用inflate和findViewById,從而減少已耗用時間。
代碼如下:
private LayoutInflater mInflater =
(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder; // 該容器用來存放控制項對象
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_icon_text, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder); // 將存放對象的容器存進視圖對象中
} else {
holder = (ViewHolder) convertView.getTag(); // 直接拿出控制項對象
}
text.setText(textData[position]);
icon.setImageBitmap(iconData[position]);
return convertView;
}
static class ViewHolder {
TextView text;
ImageView icon;
}
不過這樣寫的條件是每個清單項目裡面的控制項都是一樣的,
如果清單項目的控制項不是一樣的,
如列表中需要使用某些清單項目來做分割
(快速記賬本(QuickCharge)中通過在列表的某些清單項目中填充日期來分割不同日期的賬目),
這種方法的效能提升就不那麼明顯了不過還是可以使用。
最暴力的方法,儲存所有建立過的View。考慮到記憶體佔用,可以用弱表來儲存這些View。
摘自 蘋果君的工作室