動手前先講一下爲什麼要用這個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(),優化了資源。