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的加载效率.

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的Android BaseAdapter实例代码: ```java public class MyAdapter extends BaseAdapter { private Context context; private ArrayList<String> data; public MyAdapter(Context context, ArrayList<String> data) { this.context = context; this.data = data; } @Override public int getCount() { return data.size(); } @Override public Object getItem(int position) { return data.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.item_layout, parent, false); viewHolder = new ViewHolder(); viewHolder.text = convertView.findViewById(R.id.text_view); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.text.setText(data.get(position)); return convertView; } private static class ViewHolder { TextView text; } } ``` 在这个例子中,我们创建了一个名为`MyAdapter`的类,它扩展了`BaseAdapter`类。我们需要实现`getCount()`、`getItem()`、`getItemId()`和`getView()`这四个方法。 `getCount()`方法返回数据集合中的项目数。 `getItem()`方法返回指定位置的数据项。 `getItemId()`方法返回指定位置的数据项的ID。 `getView()`方法创建并返回一个View对象,它将用于显示数据。在这个方法中,我们首先检查convertView是否已经存在,如果存在则重用它,否则我们从布局文件中创建一个新的View对象。然后,我们使用ViewHolder模式来优化View的创建和绑定过程,以提高ListView的性能。最后,我们将数据绑定到View对象上,并将其返回。 在这个例子中,我们使用了一个名为`ViewHolder`的私有静态内部类来缓存已经找到的子视图。这样可以避免每次调用getView()时都要调用findViewById()方法来查找子视图,提高了ListView的性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值