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

發佈了66 篇原創文章 · 獲贊 59 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章