優化ListView

Listview在Android中非常的重要,也非常的常見,我們在寫一些重型的數據顯示任務或者要在listview中加載一些圖片時候,就應該想到對其進行優化,同樣,在Android面試筆試的時候,這個問題也作爲一個十分常見的問題出現,我們現在來好好總結一下,從大的方面來說,優化listview主要可以從以下幾個方面入手。
*①Item佈局,層級越少越好,使用hierarchyview工具查看優化。
②複用convertView
③使用ViewHolder
④item中有圖片時,異步加載
⑤快速滑動時,不加載圖片
⑥item中有圖片時,應對圖片進行適當壓縮
⑦實現數據的分頁加載*

優化複用convertView ,就在MyAdapter類中的getView方法中,我們注意到,上面的寫法每次需要一個View對象時,都是去重新inflate一個View出來返回去,沒有實現View對象的複用,而實際上對於ListView而言,只需要保留能夠顯示的最大個數的view即可,其他新的view可以通過複用的方式使用消失的條目的view,而getView方法裏也提供了一個參數:convertView,這個就代表着可以複用的view對象,當然這個對象也可能爲空,當它爲空的時候,表示該條目view第一次創建,所以我們需要inflate一個view出來,所以在這裏,我們使用下面這種方式來重寫getView方法:

public View getView(int position, View convertView, ViewGroup parent) {
            View view;
            // 判斷convertView的狀態,來達到複用效果
            if (null == convertView) {
                //如果convertView爲空,則表示第一次顯示該條目,需要創建一個view
                view = View.inflate(MainActivity.this, R.layout.listview_item,
                        null);
            } else {
                //否則表示可以複用convertView
                view = convertView;
            }
            // listview_item裏只有一個textview
            TextView tv_item = (TextView) view.findViewById(R.id.tv_item);
            tv_item.setText(list.get(position));
            return view;
        }

上面是對view對象的複用做的優化,我們經過上面的優化之後,我們不需要每一個view都重新生成了。下面我們來解決下一個每一次都需要做的工作,那就是view中組件的查找:

TextView tv_item = (TextView) view.findViewById(R.id.tv_item);

實際上,findViewById是到xml文件中去查找對應的id,可以想象如果組件多的話也是挺費事的,如果我們可以讓view內的組件也隨着view的複用而複用,那該是多美好的一件事啊。。實際上谷歌也推薦了一種優化方法來做應對,那就是重新建一個內部靜態類,裏面的成員變量跟view中所包含的組件個數類型相同,我們這裏的view只包含了一個TextView,所以我們的這個靜態類如下:

private static class ViewHolder {
        private TextView tvHolder;
    }

那麼這個viewHolder類我們要如何使用纔可以達到複用效果呢?基本思路就是在convertView爲null的時候,我們不僅重新inflate出來一個view,並且還需要進行findviewbyId的查找工作,但是同時我們還需要獲取一個ViewHolder類的對象,並將findviewById的結果賦值給ViewHolder中對應的成員變量。最後將holder對象與該view對象“綁”在一塊。

當convertView不爲null時,我們讓view=converView,同時取出這個view對應的holder對象,就獲得了這個view對象中的TextView組件,它就是holder中的成員變量,這樣在複用的時候,我們就不需要再去findViewById了,只需要在最開始的時候進行數次查找工作就可以了。這裏的關鍵在於如何將view與holder對象進行綁定,那麼就需要用到兩個方法:setTag和getTag方法了:

@Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view;
            ViewHolder holder;
            // 判斷convertView的狀態,來達到複用效果
            if (null == convertView) {
                // 如果convertView爲空,則表示第一次顯示該條目,需要創建一個view
                view = View.inflate(MainActivity.this, R.layout.listview_item,
                        null);
                //新建一個viewholder對象
                holder = new ViewHolder();
                //將findviewbyID的結果賦值給holder對應的成員變量
                holder.tvHolder = (TextView) view.findViewById(R.id.tv_item);
                // 將holder與view進行綁定
                view.setTag(holder);
            } else {
                // 否則表示可以複用convertView
                view = convertView;
                holder = (ViewHolder) view.getTag();
            }
            // 直接操作holder中的成員變量即可,不需要每次都findViewById
            holder.tvHolder.setText(list.get(position));
            return view;
        }

部分內容參考自:
這個博客

發佈了30 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章