自定義BaseAdapter完美解決ListView異常:java.lang.IllegalStateException

在咱們Android 開發中,ListView是在經常使用不過的控件了。可是有時候會爆出這種異常,就搞得好尷尬了。 異常圖片 明明咱們在代碼中的確是有調用adaptor.notifyDataSetChanged()這個方法的,明顯沒問題啊。 後來我查代碼,才發現,在咱們更新過程當中大部分使用到的是異步操做,可是若是網絡很卡,而後又發出了大量的請求的話,那麼就會出現這個問題。要怎麼解決這個問題呢?java

#這是代碼android

import java.util.ArrayList;
import java.util.List;

import android.util.SparseArray; 
import android.view.View;
import android.view.ViewGroup;

/**
 * @author 肖蕾
 * @param <DataType>
 *            傳入的數據類型
 * @param <viewHolder>
 *            ViewHoler的類型
 */
public abstract class BaseAdapter<DataType, viewHolder extends BaseAdapter.Holder> extends android.widget.BaseAdapter
{
	/**
	 * 保存的數據
	 */
	private List<DataType> list = new ArrayList<DataType>();
	private List<DataType> outer_list;

	public BaseAdapter(List<DataType> list)
	{
		this.outer_list = list;
		this.list.addAll(outer_list);
	}

	@Override
	public int getCount()
	{
		return getItemCount();
	}

	@Override
	public DataType getItem(int position)
	{
		return list.get(position);
	}

	@Override
	public long getItemId(int position)
	{
		return position;
	}
	
	@Override
	public void notifyDataSetChanged()
	{
		this.list.clear();
		this.list.addAll(outer_list);
		super.notifyDataSetChanged();
	}
	
	/**
	 * View 的建立
	 * 
	 * @param parent
	 *            父控件
	 * @param viewType
	 *            類型
	 * @return
	 */
	public abstract viewHolder onCreateViewHolder(ViewGroup parent, int viewType);

	/**
	 * ViewHolder與數據的綁定
	 * 
	 * @param holder
	 *            viewHoler對象
	 * @param data
	 *            數據
	 * @param position
	 *            定位
	 */
	public abstract void onBindViewHolder(viewHolder holder, DataType data, int position);

	public int getItemCount()
	{
		if (list == null)
		{
			return 0;
		}
		return list.size();
	}

	public int getItemViewType(DataType data, int position)
	{
		return super.getItemViewType(position);
	}

	@SuppressWarnings("unchecked")
	@Override
	public View getView(int position, View convertView, ViewGroup parent)
	{
		viewHolder holder = null;
		DataType data = list.get(position);
		if (convertView == null)
		{
			holder = onCreateViewHolder(parent, getItemViewType(data, position));
			convertView = holder.getRootView();
		} else
		{
			holder = (viewHolder) convertView.getTag();
		}
		onBindViewHolder(holder, data, position);
		return convertView;
	}

	public static class Holder
	{
		private View root;
		private SparseArray<View> store = new SparseArray<View>();
		
		@SuppressWarnings("unchecked")
		public <T extends View> T get(int id) 
		{
			View result = store.get(id);
			if(result == null)
			{
				result = root.findViewById(id);
				store.append(id, result);
			}
			return (T) result;
		}

		public Holder(View view)
		{
			this.root = view;
		}

		public View getRootView()
		{
			root.setTag(this);
			return root;
		}
	}
}

#使用方法網絡

public class mAdapter extends BaseAdaptor<String, BaseAdaptor.Holder>
{
    public mAdapter(List<String> list)
    {
        super(list);
    }
    /**
    * 新建一個ViewHoler
    */
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        View view = View.inflate(parent.getContext(), R.layout.item, null);
        Holder holder = new Holder(view);
        return holder;
    }
    /**
    * ViewHoler與數據綁定
    */
    @Override
    public void onBindViewHolder(Holder holder, String data, int position)
    {
        TextView text = holder.get(R.id.text);
        text.setText(data);
    }
}

#原理app

原理是什麼呢?咱們在adaptor內部就封裝了一個List用於保存用戶傳過來的List數據,咱們這裏只是對外部的list有一個引用,可是真正使用到的list,倒是內部的List,經過每一次調用notifyDataSetChanged()方法,則自動將內部的list數據與外部的list數據同步一次。再調用父類的更新、這樣,咱們玩來玩去就是外部的list,並不會對內部listview使用到的list有任何影響。就完美屏蔽了這個異常了。異步

#另外ide

分享一句我最喜歡的歌詞: 若是那兩個字沒有顫抖 我不會發現我難受 怎麼說出口也不會是分手this

若是對於明天沒有要求 牽牽手就像旅遊(女朋友) 成千上萬個門口 總有一我的要先走code

懷抱既然不能逗留 何不在離開的時候 一邊享受一邊淚流對象

相關文章
相關標籤/搜索