android BaseAdapter多布局缓存

 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); <span style="font-size:24px;"> <span style="color:#FF0000;">//方法一,得到布局类型 </span></span>
    
    int getViewTypeCount();      <span style="font-size:24px;color:#FF0000;"> // 方法二,得到布局总</span>
    
    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);
    }

   <span style="color:#FF0000;"> public int getItemViewType(int position) {
        return 0;
    }</span>

    <span style="color:#FF0000;">public int getViewTypeCount() {
        return 1;
    }</span>
    
    public boolean isEmpty() {
        return getCount() == 0;
    }
}
 有了这两个方法后,我们只需重写这两个方法即可,下面是我重写的Adapter代码:

 

<span style="font-size:18px;">/**********************************************************
 * @文件名称:CountryListAdapter.java
 * @文件作者:rzq
 * @创建时间:2014年7月22日 下午2:33:43
 * @文件描述:国家列表适配器
 * @修改历史:2014年7月22日创建初始版本
 **********************************************************/
public class CountryListAdapter extends BaseAdapter {
	private Context mContext;
	private ArrayList<Country> dataList;
	private Country country;
	private ViewHolder holder1;
	private ViewHolder holder2;

	public CountryListAdapter(Context context, ArrayList<Country> 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;
	}
}</span>
  这样确保了内存不会溢出.也可以提高ListView的加载效率.

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。