ListView是App开发中最常见的控件之一了,与之相随的则是BaseAdapter的使用,BaseAdapter的作用则是为我们的ListView提供数据源,普通的用法相信大家都会用,今天主要说明一下,列表中如果有多种样式的ItemView时,应该如何去高效的加载.
先看一下效果图:
如图所示:整个列表中存在着两种样式的ItemView,开始用传统的ConvertView去缓存子项时,发现两种布局一滑动就出现了错乱,后来为了项目进度,看到没有发生内存溢出后就没有用ConvertView做子View的缓存,今天在翻看Adapter及其子类的源码时发现,如下代码,瞬间想到之前没有对多布局多缓存的问题,于是上网查看了一下,果然就是用这几个方法去实现,代码如下:
public interface Adapter { void registerDataSetObserver(DataSetObserver observer); void unregisterDataSetObserver(DataSetObserver observer); int getCount(); Object getItem(int position); long getItemId(int position); boolean hasStableIds(); View getView(int position, View convertView, ViewGroup parent); static final int IGNORE_ITEM_VIEW_TYPE = AdapterView.ITEM_VIEW_TYPE_IGNORE; int getItemViewType(int position); //方法一,得到布局类型 int getViewTypeCount(); // 方法二,得到布局总 static final int NO_SELECTION = Integer.MIN_VALUE; /** * @return true if this adapter doesn't contain any data. This is used to determine * whether the empty view should be displayed. A typical implementation will return * getCount() == 0 but since getCount() includes the headers and footers, specialized * adapters might want a different behavior. */ boolean isEmpty(); }
就是红色注释出的两个方法,而BaseAdapter已经帮我们提供了默认的实现,才使得我们没有关注到这两个方法,BaseAdapter的默认实现如下:
package android.widget; import android.database.DataSetObservable; import android.database.DataSetObserver; import android.view.View; import android.view.ViewGroup; public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter { private final DataSetObservable mDataSetObservable = new DataSetObservable(); public boolean hasStableIds() { return false; } public void registerDataSetObserver(DataSetObserver observer) { mDataSetObservable.registerObserver(observer); } public void unregisterDataSetObserver(DataSetObserver observer) { mDataSetObservable.unregisterObserver(observer); } public void notifyDataSetChanged() { mDataSetObservable.notifyChanged(); } public void notifyDataSetInvalidated() { mDataSetObservable.notifyInvalidated(); } public boolean areAllItemsEnabled() { return true; } public boolean isEnabled(int position) { return true; } public View getDropDownView(int position, View convertView, ViewGroup parent) { return getView(position, convertView, parent); } public int getItemViewType(int position) { return 0; } public int getViewTypeCount() { return 1; } public boolean isEmpty() { return getCount() == 0; } }有了这两个方法后,我们只需重写这两个方法即可,下面是我重写的Adapter代码:
/**********************************************************
* @文件名称:CountryListAdapter.java
* @文件作者:rzq
* @创建时间:2014年7月22日 下午2:33:43
* @文件描述:国家列表适配器
* @修改历史:2014年7月22日创建初始版本
**********************************************************/
public class CountryListAdapter extends BaseAdapter {
private Context mContext;
private ArrayList dataList;
private Country country;
private ViewHolder holder1;
private ViewHolder holder2;
public CountryListAdapter(Context context, ArrayList dataList) {
this.mContext = context;
this.dataList = dataList;
}
@Override
public int getCount() {
return dataList.size();
}
@Override
public Object getItem(int position) {
return dataList.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
country = (Country) dataList.get(position);
int type = getItemViewType(position);
if (convertView == null) {
switch (type) {
case 0:
holder1 = new ViewHolder();
convertView = LayoutInflater.from(mContext)
.inflate(R.layout.catagories_expandlistview_group,
parent, false);
holder1.textView = (TextView) convertView
.findViewById(R.id.catagories_group_textview);
convertView.setTag(holder1);
break;
case 1:
holder2 = new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(
R.layout.register_expandlistview_child, parent, false);
holder2.textView = (TextView) convertView
.findViewById(R.id.register_child_textview);
holder2.imageView = (ImageView) convertView
.findViewById(R.id.register_country_flag);
convertView.setTag(holder2);
break;
}
} else {
switch (type) {
case 0:
holder1 = (ViewHolder) convertView.getTag();
break;
case 1:
holder2 = (ViewHolder) convertView.getTag();
break;
}
}
switch (type) {
case 0:
holder1.textView.setText(country.getIndexChar());
break;
case 1:
holder2.textView.setText(country.getCountryName());
holder2.imageView.setImageDrawable(country.getFlagDrawable());
break;
}
return convertView;
}
@Override
public int getItemViewType(int position) {
country = (Country) getItem(position);
if (country.isGroup()) {
return 0;
} else {
return 1;
}
}
@Override
public int getViewTypeCount() {
return 2;
}
private static class ViewHolder {
private TextView textView;
private ImageView imageView;
}
}
这样确保了内存不会溢出.也可以提高ListView的加载效率.