如果是繼承ArrayAdapter,SimpleAdapter的時(shí)候,由于父類本身維護(hù)了一個(gè)List锋爪,所以當(dāng)有數(shù)據(jù)更新的時(shí)候丙曙,盡量用adapter的add,這樣可以保證getCount()返回的值是正確其骄。
這里面涉及到的一個(gè)比較重要的重寫函數(shù)就是getView
在getView中有三種方式實(shí)現(xiàn)view的返回亏镰。
第一種方式:
最簡單也是最容易理解的是每一個(gè)view都通過inflate生成一個(gè)新的view進(jìn)行返回
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(context);
View item = inflater.inflate(R.layout.list_item_icon_text, null);
((TextView) item.findViewById(R.id.text)).setText(DATA[position]);
((ImageView) item.findViewById(R.id.icon)).setImageBitmap(
return item;
}
這種方式,在數(shù)據(jù)量小的時(shí)候拯爽,劣勢不明顯索抓,但是當(dāng)一個(gè)listview里面有大量條目時(shí),這種方式就顯得非常浪費(fèi)毯炮。因?yàn)槊恳淮蝘tem的出現(xiàn)逼肯,消失或者更新時(shí),都需要重新inflate桃煎。給內(nèi)存造成了很大的消耗篮幢。
那么還有什么方式可以節(jié)省開銷呢?
第二種方式:
我們看看getView函數(shù)里面conertview的是干啥的为迈。查看官方文檔后發(fā)現(xiàn):
convertView - The old view to reuse, if possible. Note: You should check that this view is non-null and of an appropriate type before using. If it is not possible to convert this view to display the correct data, this method can create a new view. Heterogeneous lists can specify their number of view types, so that this View is always of the right type (see Adapter.getViewTypeCount() and Adapter.getItemViewType(int)).
注:
getViewTypeCount()是用來當(dāng)listview中有不同的種類的item三椿,比如分割線之類的時(shí)候,用getItemViewType返回某個(gè)item的類型葫辐,然后坐不同的
原來converView是用來重用view的赋续。經(jīng)過查找別的資料。找到了一張比較經(jīng)典的圖如下:
這張圖清楚的描述了listview是如何重用view的另患。listview通過getview分別請求所有可見項(xiàng)目纽乱。此時(shí)converview是空的。
當(dāng)item1滑動出屏幕后昆箕,item8從下面滑動出來鸦列,此時(shí)又要調(diào)用getview,但是此時(shí)的converview已經(jīng)不再為空了鹏倘,而是上次一劃出屏幕的item1薯嗤,此時(shí)我們只需要重新修改下item1的數(shù)據(jù),而不必重新創(chuàng)建一個(gè)新的view纤泵。
這樣就節(jié)省了內(nèi)存骆姐。
那么由此我們得到了第二種方式
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item, parent, false);
}
((TextView) convertView.findViewById(R.id.text)).setText(DATA[position]);
((ImageView) convertView.findViewById(R.id.icon)).setImageBitmap(
(position & 1) == 1 ? mIcon1 : mIcon2);
return convertView;
}
這種方式里面镜粤,我們通過converview找到對應(yīng)需要修改的text和ico,然后修改數(shù)據(jù)玻褪,進(jìn)行返回肉渴。
有人會說,上面不已經(jīng)解決了重用的問題了么带射,還有第三種方式同规?
第三種方式:google推薦
static class ViewHolder {
TextView text;
ImageView icon;
}
這里定義了一個(gè)內(nèi)部靜態(tài)類,
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_icon_text,
parent, false);
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();
}
holder.text.setText(DATA[position]);
holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
return convertView;
}
然后用convertView.setTag(holder)的方式將之前通過findViewById找到的textview與ImageView放入converivew對象中窟社。
這樣當(dāng)再次重用converview的時(shí)候券勺,就不必再次利用findViewById來查找了,省掉了開銷灿里。