(轉載註明:http://blog.csdn.net/itermeng/article/details/52149426)
一. listView 的學習
衆所周知ListView 是一個控件,一個在垂直滾動的列表中顯示條目的一個控件。
使用方法爲:
1. 佈局添加Listview
2. 在對應的activity找到listview
3. 創建一個Adapter適配器繼承BaseAdapter,封裝4個方法(如下圖)
getcount: 返回listview顯示的條目總數。
getItem : 返回當前點擊listview的條目。
getItemId : 返回點擊條目對應在listview中的位置。
getview:告訴listview每個條目顯示的內容。
@Override
public int getCount() {
return 0;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return null;
}
4. 創建Adapter的一個對象,設置給listview。 listview.setAdapter(ListAdapter adapter);
二. listView 的優化
1.初步優化
依次封裝以上4個方法,其中最重點的是 getview方法,主要的優化也是在其中。
public View getView(int position, View convertView, ViewGroup parent)
{
return null;
}
注意觀察getView方法中的參數,position爲點擊條目的具體位置,重點是 convertView ,一個listview中會有許多條目,而一個條目中可能由幾個小控件(例如TextView、Button)組成,而 convertView指的是一個單獨條目(View對象),它包括了那幾個小控件。
爲了讓listview呈現出條目,在getView方法中我們需要不停的重新聲明view對象,將layout佈局inflate轉換成view後,用findViewById獲取一個條目中的具體控件進行賦值操作,如果需要大量條目展示,無疑這會消耗內存。
複用convertView : getview方法會傳進來一個convertView,convertView是指曾經使用過的view對象,可以被重複使用,但是在使用前需要判斷是否爲空,不爲空直接複用,並作爲getview方法的返回對象。(如上圖)
所以我們的第一步優化就是複用convertView(如下圖所示)
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if(convertView != null){//判斷converView是否爲空,不爲空重新使用
view = (TextView) convertView;
}else{
view = new TextView(mContext);//創建一個textView對象
}
return view;
}
再進行 if 判斷之後,即複用完convertView對象後,再用findViewById獲取小控件進行展示操作。
//2.獲取view上的子控件對象
TextView item_tv_title= (TextView) view.findViewById(R.id.item_tv_title);
//3.獲取postion位置條目對應的list集合中的新聞數據,Bean對象
NewsBean newsBean = list.get(position);
//4.將數據設置給這些子控件做顯示
item_tv_title.setText(newsBean.title);
這樣看起來解決了問題,其實不然!如果現在需要展示100條 條目,雖然複用了對象,但是這意味着 findViewById的操作要重複100次,你的可用內存會慢慢減少,最後手機程序崩潰!(如下圖)
2.完全優化
優化重點:
(1):複用convertView
(2):複用ViewHolder讓其減少findViewById()次數
(3):static ViewHolder
(4):分頁算法
如上所說,不要去一味的 findViewByID(),它是一個耗時的操作,需要優化,使用viewHolder類,它把每一個條目View放在Holder中,當getView方法第一次創建convertView對象時,會把這些條目view找出來。然後用convertView的setTag將viewHolder設置到Tag中,這樣下次呈現ListView時會直接從Tag中取出。當第二次複用convertView時,只需從convertView中getTag取出即可。(代碼如下)
public View getView(int position, View convertView, ViewGroup parent) {
//1,複用convertView
//複用viewHolder步驟一
ViewHolder holder = null;
if(convertView == null){
convertView = View.inflate(getApplicationContext(), R.layout.listview_item, null);
//2,減少findViewById()次數
//複用viewHolder步驟三
holder = new ViewHolder();
//複用viewHolder步驟四
viewHolder.text1 = convertView.findViewById(R.id.text1);
//複用viewHolder步驟五
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
viewHolder.text1.setText("文本內容");
}
//複用viewHolder步驟二
static class ViewHolder{
TextView text1;
}
以上代碼解析:
(1) convertView爲空,代表當前條目是首次構建,就需要inflate轉換佈局,用findViewByID查找小控件,這是爲了後面的條目去進行復用。
(2)創建一個ViewHolder對象,去存儲第一次找到的所有的小控件。當前的viewHolder對象,又由convertView去做存儲。 setTag(viewHolder)
(3)在複用convertView的條目展示的時候,找到之前設置過的tag . ViewHolder viewHolder = getTag()
. viewHolder中就包含第一次構建時findViewById找過的小控件。
以上即爲 listView控件的優化過程,至於分頁涉及到 數據庫分頁查詢,暫時不寫。關於優化的講解,其實直接講第二點(完全優化)即可,但是我想循序漸進,因爲初學者的我剛開始用listView使用得都是(初步優化),漸漸的才發現listView需要更徹底的優化,想讓大家體會一點點深入的過程。希望對大家有所幫助 :)