Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android BaseAdapter多布局緩存

android BaseAdapter多布局緩存

編輯:關於Android編程

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

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved