安卓控件 listView 的學習及優化 (ConvetView、viewHolder)

(轉載註明: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需要更徹底的優化,想讓大家體會一點點深入的過程。希望對大家有所幫助 :)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章