在平時的項目中經(jīng)常使用到listiview顯示列表,很多時候,我們都是自定義一個adapter,然后繼承BaseAdapter,并重寫相關(guān)方法,最后在這個adapter類里寫一個ViewHolder內(nèi)容類,用來緩存控件用。為了提高效率,一個很實用的ViewHolder是很有必要的。
平時使用的:
public class MyListAdapter extends BaseAdapter {
private Context context;
private List<Data> list;
public MyListAdapter(Context context, List<Data> list) {
this.context = context;
this.list = list;
}
@Override
public int getCount() {
return list == null ? 0 : list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
MyViewHolder holder = null;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.list_item,viewGroup,false);
holder = new MyViewHolder();
holder.iv = (ImageView) convertView.findViewById(R.id.item_image);
holder.tv = (TextView) convertView.findViewById(R.id.item_text);
convertView.setTag(holder);
} else {
holder = (MyViewHolder) convertView.getTag();
}
Data data = (Data) getItem(position);
holder.iv.setImageResource(data.getImageId());
holder.tv.setText(data.getText());
return convertView;
}
public static class MyViewHolder {
ImageView iv;
TextView tv;
}
}
仔細觀察上面的Adapter,的確是前三個方法一樣。我們要是可以全部抽出來就好了。所以可以抽出來,寫一個泛型使其變成一個抽象的基類,繼承自BaseAdapter.其子類只需要去關(guān)心其getView方法。
public class ViewHolder {
// 添加私有構(gòu)造函數(shù)防止外部實例化
private ViewHolder() {
}
/**
* 用來緩存控件,優(yōu)化加載
* @param view itemView的布局
* @param id itemView布局中需要緩存控件的id
* @return 緩存后的控件(textView、imageView...等控件)
*/
@SuppressWarnings("unchecked")
public static View get(View view, int id) {
// 獲取itemView的ViewHolder對象,并將其轉(zhuǎn)型為SparseArray<View>
SparseArray<View> viewHolder = (SparseArray<View>) view.getTag();
if (viewHolder == null) {
// 如果viewHolder為空,就新建一個
viewHolder = new SparseArray<View>();
// 給view設置tag標簽
view.setTag(viewHolder);
}
// 根據(jù)控件的id獲取itemView布局的控件
View childView = viewHolder.get(id);
if(childView == null){
// 如果還沒有緩存該控件,那么就根據(jù)itemView找到該控件
childView = view.findViewById(id);
// 緩存該控件
viewHolder.put(id, childView);
}
// 返回緩存好的控件
return childView;
}
}
在adapter中直接使用,會極大地提高開發(fā)效率
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
// 布局泵獲取itemView的布局
convertView = inflater.inflate(R.layout.listview_test, null);
}
// 使用Viewholder類的靜態(tài)方法緩存控件,并返回緩存后的控件
TextView tv_test = (TextView) ViewHolder.get(convertView, R.id.tv_test);
// 設置內(nèi)容
tv_test.setText(list.get(position));
return convertView;
}