




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
【移動應(yīng)用開發(fā)技術(shù)】Android中復(fù)用問題哲理性解析
Android中列表的復(fù)用機(jī)制提高了APP的運(yùn)行效率,但隨之而來的復(fù)用的問題總是讓程序員們頭痛,一個bug找頭天也找不到。我就把自己解決這方面的經(jīng)驗(yàn)貢獻(xiàn)出來供大家參考:問題1:什么是復(fù)用
復(fù)用其實(shí)指的是復(fù)用View,而綁定View的數(shù)據(jù)是變化的。問題2:復(fù)用的原理探究
為了徹底弄清楚復(fù)用的原理,和特地寫了段小程序。
Adapter代碼:
class
MyAdapter
extends
BaseAdapter{
@Override
public
int
getCount()
{
return
20;
}
@Override
public
Object
getItem(int
position)
{
return
null;
}
@Override
public
long
getItemId(int
position)
{
return
position;
}
@Override
public
View
getView(int
position,
View
convertView,
ViewGroup
parent)
{
Log.i(TAG,
"aaaaaaaaaa
getView:
position
=
"
+
position
+
",convertView
=
"
+
convertView);
ViewHolder
holder;
if(convertView
==
null){
convertView
=
LayoutInflater.from(SimpleCheckBoxListActivity.this).inflate(R.layout.adapter_simple_checkbox_item,null,false);
holder
=
new
ViewHolder();
holder.tv
=
(TextView)
convertView.findViewById(R.id.tv);
holder.cb
=
(CheckBox)
convertView.findViewById(R.id.cb);
convertView.setTag(holder);
}else{
holder
=
(ViewHolder)
convertView.getTag();
}
holder.tv.setText("index
=
"
+
position);
Log.i(TAG,
"bbbbbbbbbb
getView:
position
=
"
+
position
+
",convertView
=
"
+
convertView.toString());
//將convertView緩存起來,方便后面的分析。
itemViews.put(position,convertView);
//分析當(dāng)前position是否復(fù)用了之前哪個位置的view
int
reusePosition
=
analyseReusedWhichPosition(position);
if(reusePosition
!=
-1){
Log.i(TAG,
"getView:
位置
"
+
position
+
"復(fù)用了位置"
+
reusePosition
+
"的view");
}
return
convertView;
}
class
ViewHolder{
TextView
tv;
CheckBox
cb;
}
//分析當(dāng)前position是否復(fù)用了之前哪個位置的view
private
int
analyseReusedWhichPosition(int
currentPosition){
View
currentPositionView
=
itemViews.get(currentPosition);
for
(int
i
=
0;
i
<
currentPosition;
i++)
{
View
beforePositionView
=
itemViews.get(i);
if(beforePositionView
==
null){
continue;
}
if(beforePositionView
==
currentPositionView){
return
i;
}
}
return
-1;
}
}
日志分析:
1)程序初次運(yùn)行
打印的日志:
aaaaaaaaaa
getView:
position
=
0,convertView
=
null
bbbbbbbbbb
getView:
position
=
0,convertView
=
android.widget.LinearLayout{42eceab0
V.E
I.
0,0-0,0}
aaaaaaaaaa
getView:
position
=
1,convertView
=
null
bbbbbbbbbb
getView:
position
=
1,convertView
=
android.widget.LinearLayout{42ee4650
V.E
I.
0,0-0,0}
aaaaaaaaaa
getView:
position
=
2,convertView
=
null
bbbbbbbbbb
getView:
position
=
2,convertView
=
android.widget.LinearLayout{42ee6140
V.E
I.
0,0-0,0}
aaaaaaaaaa
getView:
position
=
3,convertView
=
null
bbbbbbbbbb
getView:
position
=
3,convertView
=
android.widget.LinearLayout{42ee7c10
V.E
I.
0,0-0,0}
aaaaaaaaaa
getView:
position
=
4,convertView
=
null
bbbbbbbbbb
getView:
position
=
4,convertView
=
android.widget.LinearLayout{42ee96e0
V.E
I.
0,0-0,0}
aaaaaaaaaa
getView:
position
=
5,convertView
=
null
bbbbbbbbbb
getView:
position
=
5,convertView
=
android.widget.LinearLayout{42eeb1e8
V.E
I.
0,0-0,0}
aaaaaaaaaa
getView:
position
=
6,convertView
=
null
bbbbbbbbbb
getView:
position
=
6,convertView
=
android.widget.LinearLayout{42eeccb8
V.E
I.
0,0-0,0}
aaaaaaaaaa
getView:
position
=
7,convertView
=
null
bbbbbbbbbb
getView:
position
=
7,convertView
=
android.widget.LinearLayout{42eee788
V.E
I.
0,0-0,0}
2)接著向下滑動,索引0沒有完全消失,索引8就出現(xiàn)了,這時還沒有復(fù)用。
打印的日志:
aaaaaaaaaa
getView:
position
=
8,convertView
=
null
bbbbbbbbbb
getView:
position
=
8,convertView
=
android.widget.LinearLayout{42ef5150
V.E
I.
0,0-0,0}
3)位置9出現(xiàn),索引0已經(jīng)完全消失(復(fù)用開始出現(xiàn))
打印的日志:
aaaaaaaaaa
getView:
position
=
9,convertView
=
android.widget.LinearLayout{42eceab0
V.E
0,-215-1080,1}
bbbbbbbbbb
getView:
position
=
9,convertView
=
android.widget.LinearLayout{42eceab0
V.E
D
0,-215-1080,1}
getView:
位置
9復(fù)用了位置0的view
可以發(fā)現(xiàn)索引9處的hashCode與索引0處的hashCode都是42eceab0
4)緊接著向下滾動到最后(注意是慢慢地滾動)
打印的日志:
aaaaaaaaaa
getView:
position
=
10,convertView
=
android.widget.LinearLayout{42ee4650
V.E
0,-213-1080,3}
bbbbbbbbbb
getView:
position
=
10,convertView
=
android.widget.LinearLayout{42ee4650
V.E
D
0,-213-1080,3}
getView:
位置
10復(fù)用了位置1的view
aaaaaaaaaa
getView:
position
=
11,convertView
=
android.widget.LinearLayout{42ee6140
V.E
0,-205-1080,11}
bbbbbbbbbb
getView:
position
=
11,convertView
=
android.widget.LinearLayout{42ee6140
V.E
D
0,-205-1080,11}
getView:
位置
11復(fù)用了位置2的view
aaaaaaaaaa
getView:
position
=
12,convertView
=
android.widget.LinearLayout{42ee7c10
V.E
0,-202-1080,14}
bbbbbbbbbb
getView:
position
=
12,convertView
=
android.widget.LinearLayout{42ee7c10
V.E
D
0,-202-1080,14}
getView:
位置
12復(fù)用了位置3的view
aaaaaaaaaa
getView:
position
=
13,convertView
=
android.widget.LinearLayout{42ee96e0
V.E
0,-201-1080,15}
bbbbbbbbbb
getView:
position
=
13,convertView
=
android.widget.LinearLayout{42ee96e0
V.E
D
0,-201-1080,15}
getView:
位置
13復(fù)用了位置4的view
aaaaaaaaaa
getView:
position
=
14,convertView
=
android.widget.LinearLayout{42eeb1e8
V.E
0,-188-1080,28}
bbbbbbbbbb
getView:
position
=
14,convertView
=
android.widget.LinearLayout{42eeb1e8
V.E
D
0,-188-1080,28}
getView:
位置
14復(fù)用了位置5的view
aaaaaaaaaa
getView:
position
=
15,convertView
=
android.widget.LinearLayout{42eeccb8
V.E
0,-213-1080,3}
bbbbbbbbbb
getView:
position
=
15,convertView
=
android.widget.LinearLayout{42eeccb8
V.E
D
0,-213-1080,3}
getView:
位置
15復(fù)用了位置6的view
aaaaaaaaaa
getView:
position
=
16,convertView
=
android.widget.LinearLayout{42eee788
V.E
0,-179-1080,37}
bbbbbbbbbb
getView:
position
=
16,convertView
=
android.widget.LinearLayout{42eee788
V.E
D
0,-179-1080,37}
getView:
位置
16復(fù)用了位置7的view
aaaaaaaaaa
getView:
position
=
17,convertView
=
android.widget.LinearLayout{42ef5150
V.E
0,-181-1080,35}
bbbbbbbbbb
getView:
position
=
17,convertView
=
android.widget.LinearLayout{42ef5150
V.E
D
0,-181-1080,35}
getView:
位置
17復(fù)用了位置8的view
aaaaaaaaaa
getView:
position
=
18,convertView
=
android.widget.LinearLayout{42eceab0
V.E
0,-195-1080,21}
bbbbbbbbbb
getView:
position
=
18,convertView
=
android.widget.LinearLayout{42eceab0
V.E
D
0,-195-1080,21}
getView:
位置
18復(fù)用了位置0的view
aaaaaaaaaa
getView:
position
=
19,convertView
=
android.widget.LinearLayout{42ee4650
V.E
0,-210-1080,6}
bbbbbbbbbb
getView:
position
=
19,convertView
=
android.widget.LinearLayout{42ee4650
V.E
D
0,-210-1080,6}
getView:
位置
19復(fù)用了位置1的view
可以看到向下慢慢滑動的時候,復(fù)用是很有規(guī)律的。
但是如果快速的向下滑動的時候,又發(fā)現(xiàn)不了什么規(guī)律:復(fù)用并非是連續(xù)的
aaaaaaaaaa
getView:
position
=
8,convertView
=
android.widget.LinearLayout{42f9a780
V.E
0,-85-1080,131}
bbbbbbbbbb
getView:
position
=
8,convertView
=
android.widget.LinearLayout{42f9a780
V.E
D
0,-85-1080,131}
getView:
位置
8復(fù)用了位置0的view
aaaaaaaaaa
getView:
position
=
9,convertView
=
android.widget.LinearLayout{42f9f818
V.E
0,384-1080,600}
bbbbbbbbbb
getView:
position
=
9,convertView
=
android.widget.LinearLayout{42f9f818
V.E
D
0,384-1080,600}
getView:
位置
9復(fù)用了位置3的view
aaaaaaaaaa
getView:
position
=
10,convertView
=
android.widget.LinearLayout{42f9dd48
V.E
0,138-1080,354}
bbbbbbbbbb
getView:
position
=
10,convertView
=
android.widget.LinearLayout{42f9dd48
V.E
D
0,138-1080,354}
getView:
位置
10復(fù)用了位置2的view
aaaaaaaaaa
getView:
position
=
11,convertView
=
android.widget.LinearLayout{42f9c278
V.E
0,-108-1080,108}
bbbbbbbbbb
getView:
position
=
11,convertView
=
android.widget.LinearLayout{42f9c278
V.E
D
0,-108-1080,108}
getView:
位置
11復(fù)用了位置1的view
aaaaaaaaaa
getView:
position
=
12,convertView
=
null
bbbbbbbbbb
getView:
position
=
12,convertView
=
android.widget.LinearLayout{42fad3a0
V.E
I.
0,0-0,0}
aaaaaaaaaa
getView:
position
=
13,convertView
=
android.widget.LinearLayout{42fa2df0
V.E
0,60-1080,276}
bbbbbbbbbb
getView:
position
=
13,convertView
=
android.widget.LinearLayout{42fa2df0
V.E
D
0,60-1080,276}
getView:
位置
13復(fù)用了位置5的view
aaaaaaaaaa
getView:
position
=
14,convertView
=
android.widget.LinearLayout{42fa12e8
V.E
0,-186-1080,30}
bbbbbbbbbb
getView:
position
=
14,convertView
=
android.widget.LinearLayout{42fa12e8
V.E
D
0,-186-1080,30}
getView:
位置
14復(fù)用了位置4的view
aaaaaaaaaa
getView:
position
=
15,convertView
=
android.widget.LinearLayout{42fa48c0
V.E
0,-150-1080,66}
bbbbbbbbbb
getView:
position
=
15,convertView
=
android.widget.LinearLayout{42fa48c0
V.E
D
0,-150-1080,66}
getView:
位置
15復(fù)用了位置6的view
aaaaaaaaaa
getView:
position
=
16,convertView
=
android.widget.LinearLayout{42f9a780
V.E
0,78-1080,294}
bbbbbbbbbb
getView:
position
=
16,convertView
=
android.widget.LinearLayout{42f9a780
V.E
D
0,78-1080,294}
getView:
位置
16復(fù)用了位置0的view
aaaaaaaaaa
getView:
position
=
17,convertView
=
android.widget.LinearLayout{42f9f818
V.E
0,13-1080,229}
bbbbbbbbbb
getView:
position
=
17,convertView
=
android.widget.LinearLayout{42f9f818
V.E
D
0,13-1080,229}
getView:
位置
17復(fù)用了位置3的view
aaaaaaaaaa
getView:
position
=
18,convertView
=
android.widget.LinearLayout{42f9dd48
V.E
0,-28-1080,188}
bbbbbbbbbb
getView:
position
=
18,convertView
=
android.widget.LinearLayout{42f9dd48
V.E
D
0,-28-1080,188}
getView:
位置
18復(fù)用了位置2的view
aaaaaaaaaa
getView:
position
=
19,convertView
=
android.widget.LinearLayout{42fa6390
V.E
0,-168-1080,48}
bbbbbbbbbb
getView:
position
=
19,convertView
=
android.widget.LinearLayout{42fa6390
V.E
D
0,-168-1080,48}
getView:
位置
19復(fù)用了位置7的view5)最后,向上滾動到索引為0的位置
aaaaaaaaaa
getView:
position
=
11,convertView
=
android.widget.LinearLayout{4304de70
V.E
0,-212-1080,4}
bbbbbbbbbb
getView:
position
=
11,convertView
=
android.widget.LinearLayout{4304de70
V.E
D
0,-212-1080,4}
getView:
位置
11復(fù)用了位置8的view
aaaaaaaaaa
getView:
position
=
10,convertView
=
android.widget.LinearLayout{4303ee70
V.E
0,1829-1080,2045}
bbbbbbbbbb
getView:
position
=
10,convertView
=
android.widget.LinearLayout{4303ee70
V.E
D
0,1829-1080,2045}
getView:
位置
10復(fù)用了位置1的view
aaaaaaaaaa
getView:
position
=
9,convertView
=
android.widget.LinearLayout{43040940
V.E
0,1829-1080,2045}
bbbbbbbbbb
getView:
position
=
9,convertView
=
android.widget.LinearLayout{43040940
V.E
D
0,1829-1080,2045}
getView:
位置
9復(fù)用了位置2的view
aaaaaaaaaa
getView:
position
=
8,convertView
=
android.widget.LinearLayout{4303d378
V.E
0,1830-1080,2046}
bbbbbbbbbb
getView:
position
=
8,convertView
=
android.widget.LinearLayout{4303d378
V.E
D
0,1830-1080,2046}
getView:
位置
8復(fù)用了位置0的view
aaaaaaaaaa
getView:
position
=
7,convertView
=
android.widget.LinearLayout{430474b8
V.E
0,1825-1080,2041}
bbbbbbbbbb
getView:
position
=
7,convertView
=
android.widget.LinearLayout{430474b8
V.E
D
0,1825-1080,2041}
getView:
位置
7復(fù)用了位置6的view
aaaaaaaaaa
getView:
position
=
6,convertView
=
android.widget.LinearLayout{43048f88
V.E
0,1824-1080,2040}
bbbbbbbbbb
getView:
position
=
6,convertView
=
android.widget.LinearLayout{43048f88
V.E
D
0,1824-1080,2040}
aaaaaaaaaa
getView:
position
=
5,convertView
=
android.widget.LinearLayout{43043ee0
V.E
0,1822-1080,2038}
bbbbbbbbbb
getView:
position
=
5,convertView
=
android.widget.LinearLayout{43043ee0
V.E
D
0,1822-1080,2038}
getView:
位置
5復(fù)用了位置4的view
aaaaaaaaaa
getView:
position
=
4,convertView
=
android.widget.LinearLayout{430459e8
V.E
0,1823-1080,2039}
bbbbbbbbbb
getView:
position
=
4,convertView
=
android.widget.LinearLayout{430459e8
V.E
D
0,1823-1080,2039}
aaaaaaaaaa
getView:
position
=
3,convertView
=
android.widget.LinearLayout{43042410
V.E
0,1829-1080,2045}
bbbbbbbbbb
getView:
position
=
3,convertView
=
android.widget.LinearLayout{43042410
V.E
D
0,1829-1080,2045}
aaaaaaaaaa
getView:
position
=
2,convertView
=
android.widget.LinearLayout{4304de70
V.E
0,1826-1080,2042}
bbbbbbbbbb
getView:
position
=
2,convertView
=
android.widget.LinearLayout{4304de70
V.E
D
0,1826-1080,2042}
aaaaaaaaaa
getView:
position
=
1,convertView
=
android.widget.LinearLayout{4303ee70
V.E
0,1828-1080,2044}
bbbbbbbbbb
getView:
position
=
1,convertView
=
android.widget.LinearLayout{4303ee70
V.E
D
0,1828-1080,2044}
aaaaaaaaaa
getView:
position
=
0,convertView
=
android.widget.LinearLayout{43040940
V.E
0,1788-1080,2004}
bbbbbbbbbb
getView:
position
=
0,convertView
=
android.widget.LinearLayout{43040940
V.E
D
0,1788-1080,2004}如上所述,到底誰復(fù)用了誰是隨機(jī)不定的,這個我們也沒有必要去關(guān)心。我們只要知道position是不變的就行了。
另外,除了打日志??梢赃x中某一個位置的checkbox,然后上下滑動,如果某個checkbox也莫名的選中了,那就說明這個位置的checkbox復(fù)用了之前選中的那個checkbox。
問題3:Adapter的notifyDataSetChanged()方法作了什么事情
notifyDataSetChanged,會重新走一遍可見的position的getView方法。
問題4:復(fù)用出現(xiàn)的場景
1.if-else的坑:在Adapter中,如果綁定View的數(shù)據(jù)的時候如果有if判斷,往往很多人忘記了加else,這是大多數(shù)復(fù)用問題出現(xiàn)的根源之一。在一般情況下else不寫沒有邏輯錯誤,但是在ListView復(fù)用的情況下如果不寫錯誤就會帶來錯亂的麻煩。
實(shí)際場景:
比如每個item可能有或沒有圖片picarrList,之前我只加了if判斷,如果有圖片就顯示。但后來上下一滑動之后發(fā)現(xiàn)沒有圖片的item竟然也顯示了其它了item的圖片,于是追根溯源發(fā)現(xiàn)是這里的問題。
2.checkbox等的復(fù)用問題:果如下圖,是一個簡單的CheckBox列表
第1頁剛好0-8索引,我將0索引處的checkbox設(shè)置為選中狀態(tài),然后向下滑動,發(fā)現(xiàn)下一個出現(xiàn)的checkbox(索引為10,不是9,也不一定就是10,而是索引0完全消失之后第一個出現(xiàn)的item)竟然也選中了。
百度了一下,可以用Map<Interger,Boolean>來記錄對應(yīng)position的checkbox的選中狀態(tài)。而且網(wǎng)上的這個Map是事先就是預(yù)訂好大小的了,但實(shí)際中Map的大小是確定的。
細(xì)節(jié)1):Map<Interger,Boolean>來記錄對應(yīng)position的checkbox的選中狀態(tài),怎么初始化?
--1--可以先在成員或者構(gòu)造方法里實(shí)例化Map對象
Map<Integer,Boolean>
isTitleCheckBoxSelected
=
new
HashMap();
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 合股賣水泥合同范本
- 勞務(wù)分包單位合同范本
- 勞務(wù)合同范本車輛
- 微信租房合同范本
- 與單位簽正式合同范本
- 廠內(nèi)車間出租合同范本
- 化肥生產(chǎn)合同范本
- 做建設(shè)合同范本
- 合同范本嬰兒車
- 分期付款機(jī)器買賣合同范本
- 保密風(fēng)險評估報告
- 道路建筑材料電子教案(全)
- 《尹定邦設(shè)計學(xué)概論》試題及答案
- 黃河流域生態(tài)保護(hù)和高質(zhì)量發(fā)展知識競賽試題及答案(共52題)
- 1、1~36號元素電子排布式、排布圖
- 國網(wǎng)新聞宣傳與企業(yè)文化管理專責(zé)題庫匯總-下(判斷、簡答題)
- 職業(yè)衛(wèi)生調(diào)查表
- 某安裝公司績效考核標(biāo)準(zhǔn)表
- 免疫學(xué)檢測技術(shù)的基本原理優(yōu)秀課件
- 2023年北京市實(shí)驗(yàn)動物上崗證培訓(xùn)考試題庫完美精編版
- 第一講 文化概論
評論
0/150
提交評論