通用Adapter的嘗試


轉載請標明出處:http://blog.csdn.net/lmj623565791/article/details/38902805 ,本文出自【張鴻洋的博客】

注:本文內容基本基於鴻洋大神的博客,地址在上面,可以自行閱讀。

1.通用Adapter(針對ListView,GridView)

由於作者水平有限,參考大神的博客,自己試着寫了寫,目前運用在listview和gridview中,對於recycleView和Viewpager的兼容還是不行的,不過大神博客裏上傳到Git上的那個版本是支持recycleview的,至於viewpager,個人觀點,應該可以整合到一起,就會變成一個全通用的Adapter了。之所以這麼說是因爲之前嘗試過一次,公用一個adapter,實現baseadapter,繼承pageradapter,所有需要重寫的方法都重寫,當時只能過做到簡單的顯示,後來就放在一邊就沒繼續研究,之後有時間會嘗試寫一寫。

2.代碼

具體的內容大神的博客裏已經將的很詳細了,而且對於經常寫adapter的人來說閱讀起來並不費勁,我就把我自己寫過的總體貼一下,有問題歡迎指出。

public class ViewHolder extends RecyclerView.ViewHolder{
private final SparseArray<View> mViews;
private View mConvertView;
private int mPosition;
private int mlayoutId;
private Context mContext;
private ViewHolder(Context context,View itemView,ViewGroup parent,int position){
	super(itemView);
	mContext=context;
	mConvertView=itemView;
	mPosition=position;
	mViews=new SparseArray<View>();
	mConvertView.setTag(this); 
}
//獲得ViweHolder對象
public static ViewHolder get(Context context,View convertView,ViewGroup parent,int layoutID,int position){
	if(convertView==null){
		View itemView=LayoutInflater.from(context).inflate(layoutID, parent,false);
		ViewHolder viewHolder = new ViewHolder(context, itemView, parent, position);
		viewHolder.mlayoutId=layoutID;
		return viewHolder;
	}else{
		ViewHolder holder = (ViewHolder) convertView.getTag();
		holder.mPosition=position;
		return holder;
	}
}
public <T extends View> T getView(int viewId){
	View view=mViews.get(viewId);
	if(view==null){
		view=mConvertView.findViewById(viewId);
		mViews.put(viewId, view);
	}
	return (T)view;
}
public View getConvertView(){
	return mConvertView;
}
//設置各種輔助方法
public ViewHolder setText(int viewId,String text){
	TextView view=getView(viewId);
	view.setText(text);
	return this;
}
public ViewHolder setImageResource(int viewId,int drawableId){
	ImageView view=getView(viewId);
	view.setImageResource(drawableId);
	return this;
}
public ViewHolder setImageBitmap(int viewId,Bitmap bitmap){
	ImageView view=getView(viewId);
	view.setImageBitmap(bitmap);
	return this;
}
}
這次代碼中基本沒有註釋,因爲並不難,我寫的是參照大神在git上的最新的支持recycleview的版本的,可能跟大神博客裏的有些不一樣,不過基本上原理是一樣的。

關於寫通用的adapter總結看來主要是針對這幾方面:

1.繼承basedapter,把一些常用的,基本沒有改變的東西都先寫好。主要的技巧就是用到了一個泛型,解決了list集合中不同對象的困擾。

2.ViewHolder的寫法,大神的博客中也說得很詳細了,利用一個SparseArray來保存view對象,SparseArray大家可以把它看做是一個Map,只不過key只能是integer實際上那SparseArray底層的實現方式是雙數組,跟我們平時遇到的都有點不一樣,它是一個數組存放key,一個數組存放Value。貼一下源碼。

<span style="font-size:18px;">public class SparseArray<E> implements Cloneable {
    private static final Object DELETED = new Object();
    private boolean mGarbage = false;

    private int[] mKeys;
    private Object[] mValues;
    private int mSize;

    /**
     * Creates a new SparseArray containing no mappings.
     */
    public SparseArray() {
        this(10);
    }

    /**
     * Creates a new SparseArray containing no mappings that will not
     * require any additional memory allocation to store the specified
     * number of mappings.
     */
    public SparseArray(int initialCapacity) {
        initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);

        mKeys = new int[initialCapacity];
        mValues = new Object[initialCapacity];
        mSize = 0;
    }</span>
可以看出來,是雙數組結構,這樣更便於查找,至於其他的增刪改查方面的大家可以自行去看一下,個人感覺跟arraylist的實現差不多。

3.ViewHolder中對於各種控件屬性的賦值方法,個人感覺能夠想到這一點的人真是太聰明瞭,真不知道最開始是怎麼想到的。在ViewHolder中封裝了大部分常用控件的設置方法,這樣真的就是把adapter精簡到極致了,寫一個adapter只需要一句話。

4.viewholder中對於監聽器的設置,這是在大神發在git上的最新的holder中看到的,封裝了三個常用的ontouch,onclick,onlongclick方法,可以直接調用。

5.在大神的文檔中還有這樣的兩個東西MultiItemCommonAdapter和MultiItemTypeSupport,這個是用來處理不同itemType的時候使用的,最常見的就是聊天界面左右不同的item了。大家可以自行參考。

3.總結

記得第一次看大神這個文章的時候感覺,**,居然還可以這樣?再一看是2014年的文章。頓時感覺自己要努力的地方還有很多啊!準備下一篇寫一寫關於RecycleView的文章,看到大家現在都用這個,準備研究研究,對於CommonAdapter,個人感覺能簡化的就這麼多了,也會嘗試一下和pageradapter整合,不過現在都是viewpager結合fragment用,適配器也採用的是FragmentPageAdapter,這個整合難度有點大,不過個人認爲是可行了,因爲需要的方法是不同的,也不相互干擾,應該沒問題。還是貼一下CommonAdapter的代碼吧。自己也再看一遍。嗯嗯。

public  abstract class CommonAdapter<T> extends BaseAdapter{
protected LayoutInflater mInflater;
protected Context mContext;
protected List<T> mDatas;
protected int layoutID;
public CommonAdapter(Context context,List<T> mDatas,int layoutID){
	mInflater=LayoutInflater.from(context);
	this.mContext=context;
	this.mDatas=mDatas;
	this.layoutID=layoutID;
}
	@Override
	public int getCount() {
		return mDatas.size();
	}

	@Override
	public T getItem(int position) {
		// TODO Auto-generated method stub
		return mDatas.get(position);
	}

	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder viewHolder=ViewHolder.get(mContext, convertView, parent, layoutID, position);
		convert(viewHolder,getItem(position));
		return viewHolder.getConvertView();
	}
	public abstract void convert(ViewHolder viewHolder, T item) ;
		
}

基本上就是常用的方法,不同的就是泛型和getView(),並不難。

文尾附上大神的項目,發表在Git上的,有興趣的可以下下來看看,或者留郵箱。關於recycleView,百度recycleview jar 包,有很多。(剛試了下自己寫的,炸了,一直在報NoClassDefFounfError 錯誤,不報錯誤就是一直在deBug,啊啊啊,要命了。)剛嘗試下 去掉RecycleView的繼承關係就可以了。看來recycleview使用還是有很多需要學的啊。

添加了多種Item類型的支持,源碼地址:https://github.com/hongyangAndroid/base-adapter .


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章