先来看看我们最普通的Adapter是怎样的吧.
代码:
package com.example.august.commonadapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.List;
/**
* Created by August on 16/4/9.
*/
public class MyAdapter extends BaseAdapter {
private List<String> mDatas;
private Context mContext;
public MyAdapter(List<String> mDatas, Context mContext) {
this.mDatas = mDatas;
this.mContext = mContext;
}
@Override
public int getCount() {
return mDatas.size();
}
@Override
public Object getItem(int position) {
return mDatas.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(R.layout.item_text, null);
holder = new ViewHolder();
holder.mTextView = (TextView) convertView.findViewById(R.id.mTextView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.mTextView.setText(mDatas.get(position));
return convertView;
}
class ViewHolder {
TextView mTextView;
}
}
每次写的Adapter都写得要死,一堆都是复用的代码,下面我们就开始封装一个自己的通用Adapter,把以后的代码量尽可能减少.
findView的时间,我们会用一个ViewHolderl来保存之前查找的view.以上的Adapter思路就是给Adapter传入一个经常调用的context参数还有适配的数据,其中构造器,getCount,getItem,getItemId,几乎是一样的.然后为了减少.其中我们找出每个Adapter可能不同的内容有哪些:
1.mDatas的类型 这个简单,我们使用泛型来解决
2.解析的Layout里面的View不确定,所以ViewHolder比较难搞
其中第二个我们稍微比较麻烦一点,但是想想也挺简单的.想象ViewHolder就是一个容器,我们把View塞进去里面就好了.那我们就要用到容器了.好了知道用容器了,那么我们需要怎样去确定要使用哪个View呢?哈哈,也很简单,你会想到Map,key就是View的ID,value就是对应的View了.但我们这里推荐使用SparseArray容器,因为它的速度比常用的Map快多了,唯一确定就是键值只能是Integer型的,但是已经足够了...
下面是我们的ViewHolder代码,我们也需要像前面一样,把holder设置到对应的converview里面去.这样我们就可以从converview里面获取已经存在的holder了,详情看代码
public class ViewHolder {
private SparseArray<View> mViews;
private View mConvertview;
public ViewHolder(View converview) {
this.mConvertview = converview;
mViews = new SparseArray<View>();
}
public static ViewHolder getHolder(Context context, View converview, int layoutID, ViewGroup parent) {
ViewHolder holder = null;
if (converview == null) {
converview = LayoutInflater.from(context).inflate(layoutID, parent, false);
holder = new ViewHolder(converview);
converview.setTag(holder);
} else {
holder = (ViewHolder) converview.getTag();
}
return holder;
}
}
这样我们就可以使用getHolder方法来去新建或取回一个ViewHolder了,有了ViewHolder还不行,我们还要获取里面的View,这里我们使用泛型去写
public <T extends View> T getView(int viewID) {
T view = (T) mViews.get(viewID);
if (view == null) {
view = (T) mConvertview.findViewById(viewID);
mViews.put(viewID, view);
}
return view;
}
这样以后我们就可以获取View并且作相应操作了
下面开始编写我们GeneralParentAdapter了,因为是通用的,所以Adapter对应的Layout就需要以参数的形式传入,mDatas也需要时泛型的.
package com.example.august.commonadapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
/**
* Created by August on 16/4/9.
*/
public class GeneralParentAdapter<T> extends BaseAdapter {
private List<T> mDatas;
private Context mContext;
private int layoutID;
private ViewHolder holder;
public GeneralParentAdapter(List<T> mDatas, Context mContext, int layoutID) {
this.mDatas = mDatas;
this.mContext = mContext;
this.layoutID = layoutID;
}
@Override
public int getCount() {
return mDatas.size();
}
@Override
public Object getItem(int position) {
return mDatas.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
}
嗯,这就是那堆让人讨厌的经常反反复复去写的代码
下面是Adapter的getView方法了,这里就要使用到ViewHolder了
@Override
public View getView(int position, View convertView, ViewGroup parent) {
holder = ViewHolder.getHolder(mContext, convertView, layoutID, parent);
TextView mTextView = holder.getView(R.id.mTextView);
mTextView.setText(mDatas.get(position));
return holder.getConverview();
}
然后我们发现,第一行和最后一行也是可以复用的,而且我们需要返回一个converView,那么我们就在ViewHolder添加一个方法吧
public View getConverview() {
return this.mConvertview;
}
继续,我们的Adapter就能用的,但是还不行,我们再把设置内容那里抽取出来,这才是每个Adapter真正的不同之处.现在我们把Adapter变成抽象类,并设置抽象方法setContent
@Override
public View getView(int position, View convertView, ViewGroup parent) {
holder = ViewHolder.getHolder(mContext, convertView, layoutID, parent);
setContent(holder, mDatas, position);
return holder.getConverview();
}
public abstract void setContent(ViewHolder holder, List<T> mDatas, int position);
最后我们就可以使用了
ItemBean.java
package com.example.august.commonadapter;
/**
* Created by August on 16/4/9.
*/
public class ItemBean {
public int imgID;
public String text;
public ItemBean(int imgID, String text) {
this.imgID = imgID;
this.text = text;
}
}
item_text.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:id="@+id/mImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/mTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:textSize="18sp" />
</LinearLayout>
调用代码
mListView = (ListView) findViewById(R.id.mListView);
List<ItemBean> mDatas = new ArrayList<ItemBean>();
for (int i = 'A'; i < 'Z'; i++) {
ItemBean itemBean = new ItemBean(R.drawable.pic, String.valueOf((char) i));
mDatas.add(itemBean);
}
GeneralParentAdapter<ItemBean> mAdapter = new GeneralParentAdapter<ItemBean>(mDatas, MainActivity.this, R.layout.item_text) {
@Override
public void setContent(ViewHolder holder, List<ItemBean> mDatas, int postion) {
TextView mTextView = holder.getView(R.id.mTextView);
mTextView.setText("666");
ImageView mImageView = holder.getView(R.id.mImageView);
mImageView.setImageResource(R.drawable.pic);
}
};
mListView.setAdapter(mAdapter);
可以看到我们需要写的代码从一堆变成了短小精悍的几行,但还不够,我们还得上天呢 哈哈.我们再给ViewHolder设置一些通用的方法,无非是什么setText,setBitmap之类的,于是VIewHolder有了...
public void setText(int viewID, String text) {
View childView = getView(viewID);
if (childView instanceof TextView) {
((TextView) childView).setText(text);
}
}
public void setBitmap(int viewID, Bitmap bitmap) {
View childView = getView(viewID);
if (childView instanceof ImageView) {
((ImageView) childView).setImageBitmap(bitmap);
}
}
最后我们继续精简
GeneralParentAdapter<ItemBean> mAdapter = new GeneralParentAdapter<ItemBean>(mDatas, MainActivity.this, R.layout.item_text) {
@Override
public void setContent(ViewHolder holder, List<ItemBean> mDatas, int postion) {
holder.setText(R.id.mTextView, mDatas.get(postion).text);
holder.setBitmap(R.id.mImageView, BitmapFactory.decodeResource(getResources(), R.drawable.pic));
}
};
最后变成了两行代码,咱们就呵呵了...大家还可以根据自己需要去封装更多的方法.
ViewHolder代码:
package com.example.august.commonadapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
/**
* Created by August on 16/4/9.
*/
public class ViewHolder {
private SparseArray<View> mViews;
private View mConvertview;
public ViewHolder(View converview) {
this.mConvertview = converview;
mViews = new SparseArray<View>();
}
public static ViewHolder getHolder(Context context, View converview, int layoutID, ViewGroup parent) {
ViewHolder holder = null;
if (converview == null) {
converview = LayoutInflater.from(context).inflate(layoutID, parent, false);
holder = new ViewHolder(converview);
converview.setTag(holder);
} else {
holder = (ViewHolder) converview.getTag();
}
return holder;
}
public <T extends View> T getView(int viewID) {
T view = (T) mViews.get(viewID);
if (view == null) {
view = (T) mConvertview.findViewById(viewID);
mViews.put(viewID, view);
}
return view;
}
public View getConverview() {
return this.mConvertview;
}
public void setText(int viewID, String text) {
View childView = getView(viewID);
if (childView instanceof TextView) {
((TextView) childView).setText(text);
}
}
public void setBitmap(int viewID, Bitmap bitmap) {
View childView = getView(viewID);
if (childView instanceof ImageView) {
((ImageView) childView).setImageBitmap(bitmap);
}
}
}
GeneralParentAdapter代码:
package com.example.august.commonadapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
/**
* Created by August on 16/4/9.
*/
public abstract class GeneralParentAdapter<T> extends BaseAdapter {
private List<T> mDatas;
private Context mContext;
private int layoutID;
private ViewHolder holder;
public GeneralParentAdapter(List<T> mDatas, Context mContext, int layoutID) {
this.mDatas = mDatas;
this.mContext = mContext;
this.layoutID = layoutID;
}
@Override
public int getCount() {
return mDatas.size();
}
@Override
public Object getItem(int position) {
return mDatas.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
holder = ViewHolder.getHolder(mContext, convertView, layoutID, parent);
setContent(holder, mDatas, position);
return holder.getConverview();
}
public abstract void setContent(ViewHolder holder, List<T> mDatas, int position);
}