Android之ListView(二) -- 基本(BaseAdapter、點擊事件)


https://www.jianshu.com/p/2b4881e00d45

 

續接上篇ArrayAdapter和SimpleAdapter。

3、BaseAdapter和ListView的優化

這種方式是通過繼承BaseAdapter自定義Adapter的方式實現,適用性也是最強的。

自定義Adapter使用方法:

1、首先布局文件中添加ListView控件(已經說過)

2、定義ListView中每一項的view布局文件,同SimpleAdapter方式中的定義

3、創建一個自定義Adapter類,該類繼承自BaseAdapter,因BaseAdapter是一個抽象類,所以繼承它必須實現它的方法。

4、activity的java代碼中為listview設置Adapter

自定義Adapter類的定義

 
 

上圖中為要實現的方法。

1、構造方法:

參數1:可以將當前上下文作為參數傳入,當前上下文必須傳入,因為要根據當前上下文導入布局對象;

參數2:要綁定的數據,因為繪制每一行的時候要同時為每個控件設置對應的數據。

2、getcount:獲取數組的長度,也即listview的item數;

3、getitem:獲取每一項的數據對象;

4、getItemId:獲取每一項的數據對象的id

5、getview:該方法在listview的每個子項被滾動到屏幕內的時候被調用。該方法設置子項的每個控件對應的數據,定義每個子項中的控件的點擊、選擇等事件的處理方法,均在該方法中設置,最后返回設置好的每一項的view。

getview參數:public View getView(int position, View convertView, ViewGroup parent)

參數1  int position:當前項的位置

參數2 View convertView:用於將之前加載好的布局進行緩存,如果不為null,則說明之前已經加載過,該參數中值為之前緩存的布局。convertView是listview的子項布局文件中最外面的一個layout。

參數3 ViewGroup parent:當前view的上層view,在一些情況下會使用到,例如,從父view中移除當前項。

下面展示一段沒有優化過的getview的代碼實現,該方法為listview的每個子項的中的每個控件綁定數據。

 
未經優化的實現代碼

以上代碼會在listview繪制每一個子項的時候調用,可以實現功能。但是會有效率問題,當我們滾動屏幕時,每顯示一個子項都要調用一次,也就意味着每次都會加載布局,加載布局是一個耗時的操作,當快速滾動且子項較多時便會成為性能瓶頸。

 
優化過的代碼

優化過的代碼使用了convertView,對convertView進行了判斷,如果為空才去加載布局,否則直接重用。同時增加了ViewHolder,ViewHolder是對子項的控件進行了緩存,這樣避免了每次都通過findViewById方法去獲取控件實例。

二、ListView,處理用戶的點擊事件

事件處理的定義,有兩種方式,一種是可以通過listview的setOnItemClickListener實現,一種通過重Adapter時定義。前一種是只要點擊子項就會觸發,后一種可以設置為點擊子項中的某一個控件才觸發,后者更強大一些。

1、setOnItemClickListener:

 
setOnItemClickListener

2、在自定義Adapter中定義某一個控件的點擊事件

 
在自定義adapter中定義R.id.more控件的點擊事件

其他事件定義同點擊事件。

 

 

 

 

 

getItemId(int position)對listview展示數據而言,並沒有什么用,返回的Id和position有什么關系全憑自己決定。另外在onclick事件中傳入的參數id,就是系統通過這個方法獲取的,請注意
getItem(int position)方便自己把對應數據轉換成對象,如果adapter中用的是自己的list或array,則不需要從這里獲取對象,該情況下也沒什么用,隨便返回一個值就是


getCount()getView(int position, View convertView, ViewGroup parent):需要好好重寫
對於listview,有個從父類ViewGroup繼承下來的View[] mChildren,於是乎listview(大概)這樣初始化:

mChildren =new View[adapter.getCount()]; for(int i=0;i<getCount();i++){ mChildren[i]=adapter.getView(i, mChildren[i], this) } 

大概的重要邏輯上,好像就這么個情況。復用的convertView就是把某個view數組的元素傳進去,最后把返回來的值給回數組,從而listview更新數據並不需要重新為子item的view申請內存空間。
注意:實際上並不就是上面這段代碼,只是把復用view的方法抽象的說下。實際上還有位置更新后前面的數組位置怎么對應后面position的細節等等。
所以不難理解listview中獲取某個正在被顯示的item的view時,需要
listview.getChildAt(position - listview.getFirstVisiblePosition())
position是listview算上前面所有行的位置,getFirstVisiblePosition()是listview顯示中第一行對應的position,getChildAt()就是返回mChildren數組中的元素。

 
 
0人點贊
 
android
 
 


作者:codeflame
鏈接:https://www.jianshu.com/p/019a8f8704be
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM