国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 系統(tǒng) > Android > 正文

android開(kāi)發(fā)中ListView與Adapter使用要點(diǎn)介紹

2020-04-11 12:15:15
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
1. Adapter.getView()

public View getView(int position, View convertView , ViewGroup parent){...}

這個(gè)方法就是用來(lái)獲得指定位置要顯示的View。官網(wǎng)解釋如下:
Get a View that displays the data at the specified position in the data set. You can either create a View manually or inflate it from an XML layout file.

當(dāng)要顯示一個(gè)View就調(diào)用一次這個(gè)方法。這個(gè)方法是ListView性能好壞的關(guān)鍵。方法中有個(gè)convertView,這個(gè)是Android在為我們而做的緩存機(jī)制。
ListView中每個(gè)item都是通過(guò)getView返回并顯示的,假如item有很多個(gè),那么重復(fù)創(chuàng)建這么多對(duì)象來(lái)顯示顯然是不合理。因此,Android提供了Recycler,將沒(méi)有正在顯示的item放進(jìn)RecycleBin,然后在顯示新視圖時(shí)從RecycleBin中復(fù)用這個(gè)View。

Recycler的工作原理大致如下:
假設(shè)屏幕最多能看到11個(gè)item,那么當(dāng)?shù)?個(gè)item滾出屏幕,這個(gè)item的View進(jìn)入RecycleBin中,第12個(gè)要出現(xiàn)前,通過(guò)getView從回收站(RecycleBin)中重用這個(gè)View,然后設(shè)置數(shù)據(jù),而不必重新創(chuàng)建一個(gè)View。

我們用Android提供的APIDemos來(lái)驗(yàn)證這個(gè)過(guò)程:

先看關(guān)鍵代碼:
復(fù)制代碼 代碼如下:

public View getView(int position, View convertView, ViewGroup parent) {
// A ViewHolder keeps references to children views to avoid unneccessary calls
// to findViewById() on each row.
ViewHolder holder;
// When convertView is not null, we can reuse it directly, there is no need
// to reinflate it. We only inflate a new View when the convertView supplied
// by ListView is null.
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_icon_text, null);
Log.v("tag", "positon " + position + " convertView is null, " + "new: " + convertView);
// Creates a ViewHolder and store references to the two children views
// we want to bind data to.
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
} else {
// Get the ViewHolder back to get fast access to the TextView
// and the ImageView.
holder = (ViewHolder) convertView.getTag();
Log.v("tag", "positon " + position + " convertView is not null, " + convertView);
}
// Bind the data efficiently with the holder.
holder.text.setText(DATA[position]);
holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
return convertView;
}

static class ViewHolder {
TextView text;
ImageView icon;
}


效果圖:

可以看到,一打開(kāi)Activity,看到10個(gè)item.

我們看看Log信息:

可以看出,每次convertView都是null, 都是新建一個(gè)View來(lái)顯示的。

當(dāng)我們向下滑動(dòng),如下圖,

由于item0和item10都顯示一半,所以item10也是新建出來(lái),但是當(dāng)要顯示item11的時(shí)候,由于item0已經(jīng)不在屏幕上,所以item11復(fù)用了item0的實(shí)例。可以從以下Log信息看出:

我們分析Log信息,可以看出item11的對(duì)象是item0, item12的對(duì)象是item1,如此類(lèi)推。

這樣,通過(guò)復(fù)用convertView,就可以避免每次都新建View,節(jié)省內(nèi)存而且優(yōu)化ListView的滑動(dòng)效果。

2. ListView的Layout XML


除了上述說(shuō)的,還有一個(gè)要點(diǎn)就是ListView在Layout XML中的描述。

先看問(wèn)題:

有時(shí),我們可能會(huì)看到一打開(kāi)ListView,getView會(huì)重復(fù)調(diào)用好次(假設(shè)屏幕最多可以看到6個(gè)item),如下圖:

一直重復(fù) 0-6, 0-5,0-5, 0-5,0-5, 0-5。而且,convertView一開(kāi)始都是同一個(gè)View,這個(gè)是因?yàn)長(zhǎng)istView的

android:layout_height="wrap_content"。

我們修改為android:layout_height="fill_parent",Log信息如下:

可以看出,修改之后ListView的getView調(diào)用恢復(fù)和Recycler的行為一致。

至于為什么使用wrap_content會(huì)出現(xiàn)重復(fù)調(diào)用的情況,我還沒(méi)有研究過(guò)。不過(guò)初步覺(jué)得是因?yàn)樵贏ndroid描繪ListView的時(shí)候,由于不清楚高度,所以使用一個(gè)item去試探ListView在屏幕中的最大高度所引起。希望有知道的朋友能夠告訴,先謝謝了!

最后,如果上面有什么地方說(shuō)錯(cuò)的話,希望能夠指出,互相進(jìn)步嘛。

補(bǔ)充:

在接著使用ListView的時(shí)候,又發(fā)現(xiàn)一個(gè)很奇怪的現(xiàn)象。調(diào)用notifyDataSetChanged()之后,ListView在重新getView()時(shí),所有的convertView的順序都逆序了。請(qǐng)看下面截圖:

這應(yīng)該是由于recycleBin是stack結(jié)構(gòu)而引起。

其它:

1. Disable divider:

android:divider="#00000000"
android:dividerHeight="0dp"

2. Disable ListView selector:

convertView.setOnClickListener(null);
如果只是要去掉顏色,可以用android:listSelector="#00000000"

3. Disable header divider:

android:headerDividersEnabled="false"
4. getItemViewType(int)與getItemViewType(int)

getItemViewType(int) can not return int value larger than getViewTypeCount().
Otherwise you will get java.lang.ArrayIndexOutOfBoundsException at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:3523)
ListView會(huì)根據(jù)不同的ViewType返回相應(yīng)type的convertView.

一般寫(xiě)法:

復(fù)制代碼 代碼如下:

getView() {
switch (getItemViewType(position)) {
case type1:
if(convertView == null) {
} else {
}
break;
case type2:
default:
if(convertView == null) {
} else {
}
break;
}
return convertView;
}
getItemViewType(int position) {
// 根據(jù)場(chǎng)景,一般有:
// 1. 不同的item type對(duì)應(yīng)的position是固定的,那么ListView的data可以分別存放
// 2. 不同的item type對(duì)應(yīng)的position是不固定的,那么可以把ListView的data統(tǒng)一放在List<Object>中,
// 然后使用instanceof來(lái)判斷Object的類(lèi)型進(jìn)而區(qū)分position對(duì)應(yīng)的view type.
}

發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 花垣县| 海城市| 奈曼旗| 长沙市| 德庆县| 章丘市| 图木舒克市| 巨鹿县| 三台县| 罗山县| 三穗县| 襄汾县| 泰兴市| 监利县| 花莲市| 鄂托克前旗| 九龙坡区| 清河县| 图们市| 星座| 尚义县| 镇康县| 旬邑县| 凤庆县| 偏关县| 平顺县| 尼玛县| 彝良县| 禹城市| 根河市| 安福县| 皋兰县| 山西省| 曲阜市| 南充市| 岑溪市| 华安县| 河源市| 修水县| 北京市| 台前县|