ListView優化,和getView方法的研究

public abstract View getView (int position, View convertView, ViewGroup parent)

Added in API level 1

Get a View that displays the data at the specified position in the data set. You can either create a View manually or inflate it from an XML layout file. When the View is inflated, the parent View (GridView, ListView...) will apply default layout parameters unless you use inflate(int, android.view.ViewGroup, boolean) to specify a root view and to prevent attachment to the root.

Parameters
position  The position of the item within the adapter's data set of the item whose view we want.
convertView  The old view to reuse, if possible. Note: You should check that this view is non-null and of an appropriate type before using. If it is not possible to convert this view to display the correct data, this method can create a new view. Heterogeneous lists can specify their number of view types, so that this View is always of the right type (see getViewTypeCount() and getItemViewType(int)).
parent The parent that this view will eventually be attached to
Returns
  • A View corresponding to the data at the specified position.
上面是google的API ,對getView()的解釋讀起來還是挺清晰的,不過就是少了點延伸。
今天在讀取數據和數據顯示到listview上的時候遇到了很多問題,首先得問題是 listView的優化,和bordercastreceiver 的發送接收問題。

在網上很多博客看到,listview可以用viewHolder這個東西進行優化,還有利用getView()方法裏的convertView進行判斷優化。看了一下代碼,感覺寫的和所講的有很多出入,很多幹擾人的地方,讀起來一頭霧水,不過還是有很多值得借鑑的地方。在一番搜索和閱讀之後,自己終於理清楚了這個東西的應用。
//ViewHolder靜態類
    static class ViewHolder
    {
        public ImageView img;
        public TextView title;
        public TextView info;
    }
    
    public class MyAdapter extends BaseAdapter
    {    
        private LayoutInflater mInflater = null;
        private MyAdapter(Context context)
        {
            //根據context上下文加載佈局,這裏的是Demo17Activity本身,即this
            this.mInflater = LayoutInflater.from(context);
        }

        @Override
        public int getCount() {
            //How many items are in the data set represented by this Adapter.
            //在此適配器中所代表的數據集中的條目數
            return data.size();
        }

        @Override
        public Object getItem(int position) {
            // Get the data item associated with the specified position in the data set.
            //獲取數據集中與指定索引對應的數據項
            return position;
        }

        @Override
        public long getItemId(int position) {
            //Get the row id associated with the specified position in the list.
            //獲取在列表中與指定索引對應的行id
            return position;
        }
        
        //Get a View that displays the data at the specified position in the data set.
        //獲取一個在數據集中指定索引的視圖來顯示數據
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            //如果緩存convertView爲空,則需要創建View
            if(convertView == null)
            {
                holder = new ViewHolder();
                //根據自定義的Item佈局加載佈局
                convertView = mInflater.inflate(R.layout.list_item, null);
                holder.img = (ImageView)convertView.findViewById(R.id.img);
                holder.title = (TextView)convertView.findViewById(R.id.tv);
                holder.info = (TextView)convertView.findViewById(R.id.info);
                //將設置好的佈局保存到緩存中,並將其設置在Tag裏,以便後面方便取出Tag
                convertView.setTag(holder);
            }else
            {
                holder = (ViewHolder)convertView.getTag();
            }
            holder.img.setBackgroundResource((Integer)data.get(position).get("img"));
            holder.title.setText((String)data.get(position).get("title"));
            holder.info.setText((String)data.get(position).get("info"));
            
            return convertView;
        }
        
    }



下面是兩個關鍵點,和各自的作用:

convertView的作用在於複用在用戶視野外的listView的行來加載當前視野中的行,可以減少UI的繪製消耗,大大優化了用戶體驗。

ViewHolder的作用在於,將listView的每一行的控件元素綁定在行上面,這樣每次在複用convertView的時候就不用再一次的 findviewbyid 去尋找,減少了開銷。

listView的優化目前我自己從網上了解的方法就是這二者,從ViewHolder的應用我自己發現其實可以有一種變種的ViewHolder的用法。
看到這一行
convertView = mInflater.inflate(R.layout.list_item, null);
我將這個LayoutInflater 
換成一個自定義的linearLayout,然後將findviewbyid這個過程放到linearLayout裏,然後在這個類中寫一個載入數據的公共方法,之後就可以在getView()中調用,複用listview行的同時也起到了viewholder的作用,因爲在構造函數中我執行了findviewbyid這個過程,載入輸入時就可以直接拿出來用。而且這樣做之後代碼量少了,邏輯也更清晰。

public View getView(int position, View convertView, ViewGroup arg2) {
        if (subject_list == null) {
			return null;
		}
        if(convertView == null){
            //首次加載默認控件
            convertView = new OneView(mContext);
        }
        OneView newView = (OneSubjectView)convertView;
        newView.updateView(subject_list.get(position)); //加載數據方法 
        convertView = newView;
		return convertView;
	}





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