ListView這個控件幾乎是每個應(yīng)用都要用到,所以,我們一定要注意它的優(yōu)化,即使你的應(yīng)用比較簡單,如果listview不優(yōu)化,同樣會出現(xiàn)oom等問題。
下面總結(jié)4條ListView的優(yōu)化方案:
第一種是convertView的復(fù)用:
就是重用convertView,這也是最簡單的一種優(yōu)化方式,就是在Adapter類的getView方法中通過判斷convertView是否為null,是的話就需要在創(chuàng)建一個視圖出來,然后給視圖設(shè)置數(shù)據(jù),最后將這個視圖返回給底層,呈現(xiàn)給用戶;如果不為null的話,其他新的view可以通過復(fù)用的方式使用已經(jīng)消失的條目view,重新設(shè)置上數(shù)據(jù)然后展現(xiàn)出來。
代碼是這樣的:
if (convertView == null){
textView = new TextView(mContext);
convertView = textView;
convertView.setTag(textView);
}else {
textView = (TextView)convertView.getTag();
convertView = textView;
}
第二種方式是使用ViewHolder(這里注意,這個名字是個通用名稱,google推薦命名,實際可以隨意):
第一種優(yōu)化方式有個缺點,就是每次在findviewById,重新找到控件,然后對控件進(jìn)行賦值,這樣會減慢加載的速度,其實我們可以創(chuàng)建一個內(nèi)部類ViewHolder,里面的成員變量和view中所包含的組件個數(shù)、類型相同,在convertview為null的時候,把findviewbyId找到的控件賦給ViewHolder中對應(yīng)的變量,就相當(dāng)于先把它們裝進(jìn)一個容器,下次要用的時候,直接從容器中獲取,這樣findviewbyId效率要高很多。
代碼是這樣寫的:
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder viewHolder = null;
if (null == convertView)
{
viewHolder = new ViewHolder();
LayoutInflater mInflater = LayoutInflater.from(mContext);
convertView = mInflater.inflate(R.layout.item_marker_item, null);
viewHolder.name = (TextView) convertView.findViewById(R.id.name);
viewHolder.description = (TextView) convertView
.findViewById(R.id.description);
viewHolder.createTime = (TextView) convertView
.findViewById(R.id.createTime);
convertView.setTag(viewHolder);
}
else
{
viewHolder = (ViewHolder) convertView.getTag();
}
MarkerItem markerItem = getItem(position);
if (null != markerItem)
{
viewHolder.name.setText(markerItem.getName());
viewHolder.description.setText(markerItem.getDescription());
viewHolder.createTime.setText(markerItem.getCreateDate());
}
return convertView;
}
private static class ViewHolder
{
TextView name;
TextView description;
TextView createTime;
}
第三種方式是由于我們的列表顯示的數(shù)據(jù)過多,而且基本都是從網(wǎng)絡(luò)獲取,會占用太多內(nèi)存,導(dǎo)致內(nèi)存溢出,所以,使用分段加載。如果數(shù)據(jù)有1000條,沒有優(yōu)化過的ListView都是會一次性把數(shù)據(jù)全部加載出來的,很顯然需要一段時間才能加載出來,我們不可能讓用戶面對著空白的屏幕等好幾分鐘,那么這時我們可以使用分段加載,比如先設(shè)置每次加載數(shù)據(jù)10條,當(dāng)用戶滑動ListView到底部的時候,我們再加載20條數(shù)據(jù)出來,然后使用Adapter刷新ListView,這樣用戶只需要等待10條數(shù)據(jù)的加載時間,這樣也可以緩解一次性加載大量數(shù)據(jù)而導(dǎo)致OOM崩潰的情況。
第四種方式是分頁加載,因為上面第三種方式其實也不能完全解決OOM崩潰的情況,雖然我們在分段中一次只增加10條數(shù)據(jù)到List集合中,然后再刷新到ListView中去,假如有10萬條數(shù)據(jù),如果我們順利讀到最后這個List集合中還是會累積海量條數(shù)的數(shù)據(jù),還是可能會造成OOM崩潰的情況,這時候我們就需要用到分頁,比如說我們將這10萬條數(shù)據(jù)分為1000頁,每一頁100條數(shù)據(jù),每一頁加載時都覆蓋掉上一頁中List集合中的內(nèi)容,然后每一頁內(nèi)再使用分批加載,這樣用戶的體驗就會相對好一些。