[Android]在Adapter的getView方法中綁定OnClickListener比較好的方法

來源:互聯網
上載者:User

標籤:android   style   blog   http   io   ar   color   os   使用   

以下內容為原創,歡迎轉載,轉載請註明

來自天天部落格:http://www.cnblogs.com/tiantianbyconan/p/4146512.html 

 

給ListView中每個item綁定點擊事件的方法,比較常見的如下這種方式:

 1 public View getView(int positon, View convertView, ViewGroup parent){ 2     if(null == convertView){ 3         convertView = LayoutInflater.from(context).inflate(R.layout.item, null); 4     } 5  6     Button button = ABViewUtil.obtainView(convertView, R.id.item_btn); 7     button.setOnClickListener(new View.OnClickListener(){ 8         @Override 9         public void onClick(View v){10             Toast.makeText(context, "position: " + position, Toast.LENGTH_SHORT).show();11         }12     });13 14 }

然後運行,當然沒問題。

但是這裡有一個可以最佳化的地方,注意代碼第7行,每次調用getView方法都會設定Button的OnClickListener,會產生很多不必要的OnClickListener對象。

所以,我們可以想到,在產生convertView時,同時設定Button的OnClickListener,convertView是被不斷地複用的,這樣的OnClickListener也就可以被不斷地服用,也就是說在第3行和第4行之間進行這一步。這樣,代碼演化到如下:

 1 public View getView(int positon, View convertView, ViewGroup parent){ 2     if(null == convertView){ 3         convertView = LayoutInflater.from(context).inflate(R.layout.item, null); 4         Button button = ABViewUtil.obtainView(convertView, R.id.item_btn); 5         button.setOnClickListener(new View.OnClickListener(){ 6             @Override 7             public void onClick(View v){ 8                 Toast.makeText(context, "position: " + position, Toast.LENGTH_SHORT).show(); 9             }10         });11     }12 }

這個代碼看上去沒什麼問題,但是問題就在onClick回調的的第8行中使用的position的時候,因為這裡使用的是匿名內部類(這個匿名內部類實現了View.OnClickListener這個介面),所以如果需要在onClick中使用position這個變數的話,需要把position聲明為final。一旦聲明了final,等到編譯之後,這個position就會被作為這個匿名內部類中的一個private的成員變數。這樣,ListView往下滾動,下面需要顯示的item會重用上面不顯示的convertView,convertView中的Button設定的OnClickListener實作類別的對象,回調onClick時,使用的position其實是該OnClickListener實作類別的成員變數position(這個position的值只是在構造的時候被初始化了而已!)。所以,這個ListView剛載入完資料後,還未滾動時,點擊螢幕上的item都是正常的,但是如果一旦滾動,有view被重用了,這個時候,position的值就錯亂了,所以在onClick中通過position擷取到的item的資料當然也是錯亂的了。

所以,要解決這個問題,就需要讓onClick方法回調的時候得到的position是個正確的值,我們可以選擇使用把當前顯示的convertView對應的position值儲存在convertView中,然後把這個convertView對象傳入OnClickListener中儲存,所以代碼演化到如下:

 1 public View getView(int positon, View convertView, ViewGroup parent){ 2     if(null == convertView){ 3         convertView = LayoutInflater.from(context).inflate(R.layout.item, null); 4         Button button = ABViewUtil.obtainView(convertView, R.id.item_btn); 5         button.setOnClickListener(new OnConvertViewClickListener(convertView, R.id.ab__id_adapter_item_position){ 6                 @Override 7                 public void onClickCallBack(View registedView, int... positionIds){ 8                     Toast.makeText(context, "position: " + positionIds[0], Toast.LENGTH_SHORT).show(); 9                 }10         });11     }12     convertView.setTag(R.id.ab__id_adapter_item_position, position);13 }

就像上面第5行這樣,Button綁定的是OnConvertViewClickListener,它是OnClickListener的一個實作類別可以儲存convertView到Listener中,到時候回調onClick方法的時候可以從儲存的convertView中擷取到當前顯示的item的position(這個position是以tag的方式儲存在convertView中的)。

當然,還需要做第12行這一步,它的目的是把當前顯示的position儲存到convertView中,提供給OnConvertViewClickListener擷取當前的position。

這樣就ok了,可以在onClickCallBack()方法中進行點擊事件的處理了,每個button永遠只有一個onClickListener。

註:使用OnConvertViewClickListener可以依賴AndroidBucket(https://github.com/wangjiegulu/AndroidBucket)項目

[Android]在Adapter的getView方法中綁定OnClickListener比較好的方法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.