利用ViewHolder優化自定義BaseAdapter

  動手前先講一下爲什麼要用這個ViewHolder,不用這個也可以實現啊,感覺雞肋有木有,可是實際上呢,既然發明肯定有存在的必要性,接下來就來簡單講一下BaseAdapter,慢慢就能理解爲什麼需要用ViewHolder來優化了!!!

當用到像ListView、Spinner、Gallery及GridView等UI顯示組件時,自然需要用到數據適配器 Adapter 這個東西

<pre style="background-color:#2b2b2b;color:#a9b7c6;font-family:'宋體';font-size:9.0pt;"><span style="color:#cc7832;"></span>
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

/**
 * Created by HD on 2016/3/9.
 */
public class MyAdapter extends BaseAdapter {
    private List<ItemBean> mList;
    private LayoutInflater mInflater;

    public MyAdapter(Context context, List<ItemBean> list) {
        this.mList = list;
        this.mInflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return mList.size();
    }

    @Override
    public Object getItem(int position) {
        return mList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
<span style="white-space:pre">	</span>return null;
 }
}



因爲這是講ViewHolder優化的,所以繼承BaseAapter這個基礎類而得到的具體幾個方法就不細寫了。

接下來介紹第一鍾方式,也是最笨的,根本沒有用到ListView控件的緩存機制。

public View getView( int position, View convertView, ViewGroup parent )
{
	View v = mInflater.inflate( R.layout.item, null );
	ImageView imageView = (ImageView) v.findViewById( R.id.iv_image );
	TextView titleView = (TextView) v.findViewById( R.id.tv_title );
	TextView contentView = (TextView) v.findViewById( R.id.tv_content );
	ItemBean bean = mList.get( position );
	imageView.setImageResource( bean.getItemImageResid() );
	titleView.setText( bean.getItemtitle() );
	contentView.setText( bean.getItemContent() );
	return(v);
}
通過LayoutInflater對象的inflate方法找到對應的模塊,根據id找到模塊,傳入數據,返回View,這是最基本的。但是也是最笨的,連緩存機制都沒有應用到。

第二種方式,還算是比較正常的,因爲已經利用到ListView的緩存機制。

public View getView( int position, View convertView, ViewGroup parent )
{
	if ( convertView == null )
	{
		convertView = mInflater.inflate( R.layout.item, null );
	}
	ImageView imageView = (ImageView) convertView.findViewById( R.id.iv_image );
	TextView titleView = (TextView) convertView.findViewById( R.id.tv_title );
	TextView contentView = (TextView) convertView.findViewById( R.id.tv_content );
	ItemBean bean = mList.get( position );
	imageView.setImageResource( bean.getItemImageResid() );
	titleView.setText( bean.getItemtitle() );
	contentView.setText( bean.getItemContent() );
	return(convertView);
}
當一個ItemView滾出界面的時候,他並沒有消失,而是儲存在converView裏面了,這時候就可以檢測這是不是null,是null就新建一個,不是就可以直接用以前儲存在converView裏的,從新給itemView傳入數據,再次顯示,這就是循環使用View,不必一直新建視圖。

第三種方式就是在第二種方式上優化產生的,因爲第二種方式在使用上,每一次循環利用VIew,需要傳入數據時,都是用findView()再次尋找控件,item比較少的時候,這樣一次次的尋找消耗的時間還可以接受,但是當item達到上千上萬乃至更多的時候,就能累加的很明顯的時間,給用戶造成很不好的用戶體驗。這時候就用到ViewHolder來優化。

public View getView( int position, View convertView, ViewGroup parent )
{
	  ViewHolder viewHolder;
        if (convertView == null) {
            viewHolder = new ViewHolder();
            convertView = mInflater.inflate(R.layout.item, null);
            viewHolder.imageView = (ImageView) convertView.findViewById(R.id.iv_image);
            viewHolder.titleView = (TextView) convertView.findViewById(R.id.tv_title);
            viewHolder.contentView = (TextView) convertView.findViewById(R.id.tv_content);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        ItemBean bean = mList.get(position);
        viewHolder.imageView.setImageResource(bean.getItemImageResid());
        viewHolder.titleView.setText(bean.getItemtitle());
        viewHolder.contentView.setText(bean.getItemContent());
        return convertView;
    }

    
}
class ViewHolder {
        public ImageView imageView;
        public TextView titleView;
        public TextView contentView;
}
先創建一個內部類ViewHolder,根據你的Item裏有多少控件設立多少屬性,如果converView爲null,就new對象,根據對象的傳入值,只findViewById()一次,然後把信息添加到Tag裏,如果不爲空,就用上次的VIew,直接獲取Tag裏面的信息進行操作,然後返回converView即可。這樣的效果是可以不用每一次都findViewById(),優化了資源。




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