【移動應(yīng)用開發(fā)技術(shù)】Android中復(fù)用問題哲理性解析_第1頁
【移動應(yīng)用開發(fā)技術(shù)】Android中復(fù)用問題哲理性解析_第2頁
【移動應(yīng)用開發(fā)技術(shù)】Android中復(fù)用問題哲理性解析_第3頁
【移動應(yīng)用開發(fā)技術(shù)】Android中復(fù)用問題哲理性解析_第4頁
【移動應(yīng)用開發(fā)技術(shù)】Android中復(fù)用問題哲理性解析_第5頁
已閱讀5頁,還剩17頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論