Android-对ListView的Adapter的一种简单封装


from:https://github.com/etao-open-source/cube-sdk/tree/master/core/src/in/srain/cube/views/list

使用示例:http://download.csdn.net/detail/goldenfish1919/8929561

1.先来看下使用方式:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listview = (ListView) this.findViewById(R.id.listview);
ListViewDataAdapter<Person> adapter = new ListViewDataAdapter<Person>(null);
adapter.setViewHolderClass(null, PersonViewHolder.class, this);
listview.setAdapter(adapter);
adapter.update(getDatas());
}
看出来跟普通的ListView的Adapter的使用唯一的区别是多了一步setViewHolderClass,其他的没有任何区别。

2.看下具体的实现

(1)ListViewDataAdapter.java

public class ListViewDataAdapter<T> extends ListViewDataAdapterBase<T> {

protected List<T> mItemDataList;

public ListViewDataAdapter(List<T> itemDataList) {
update(itemDataList);
}

@Override
public void update(List<T> list){
this.mItemDataList = list;
this.notifyDataSetChanged();
}

public List<T> getDataList() {
return mItemDataList;
}

@Override
public int getCount() {
if(mItemDataList == null){
return 0;
}else{
return mItemDataList.size();
}
}

@Override
public T getItem(int position) {
if (mItemDataList.size() <= position || position < 0) {
return null;
}
return mItemDataList.get(position);
}

@Override
public long getItemId(int position) {
return position;
}
}
它继承了ListViewDataAdapterBase,里面全是对数据的操作。转载请标明出处:http://blog.csdn.net/goldenfish1919/article/details/47039985

(2)PersonViewHolder.java

public class PersonViewHolder extends ViewHolderBase<Person>{

private Context mContext;
private TextView mName;
private ImageView mImg;

public PersonViewHolder(MainActivity context){
this.mContext = context;
}

@SuppressLint("InflateParams")
@Override
public View createView(LayoutInflater layoutInflater) {
View v = LayoutInflater.from(mContext).inflate(R.layout.item, null);
mName = (TextView)v.findViewById(R.id.name);
mImg = (ImageView)v.findViewById(R.id.image);
return v;
}

@Override
public void showData(final int position, Person itemData) {
mName.setText(itemData.getName());
mImg.setImageResource(itemData.getResId());
mName.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, ""+position, Toast.LENGTH_SHORT).show();
}
});
}
}
可以看到,这里面全是对view的操作。通过这种方式,起到了很好的分离数据与View的效果,代码变得更整洁,看起来赏心悦目。以后,在书写Adapter的时候,只需要写ViewHolder就可以,ListViewDataAdapter大部分时候都不要做任何改动,需要改的时候只要继承这个类就可以了,大大的减少了工作量。

看些是如何来实现的:

(1)ListViewDataAdapterBase:

public abstract class ListViewDataAdapterBase<T> extends BaseAdapter {

protected ViewHolderCreator<T> mViewHolderCreator;

public void setViewHolderClass(final Object enclosingInstance, final Class<?> cls, final Object... args) {
mViewHolderCreator = ViewHolderCreator.create(enclosingInstance, cls, args);
}

@SuppressWarnings("unchecked")
@Override
public View getView(int position, View convertView, ViewGroup parent) {
T itemData = getItem(position);
ViewHolderBase<T> viewHolder = null;
if (convertView == null || (!(convertView.getTag() instanceof ViewHolderBase<?>))) {
viewHolder = createViewHolder(position);
if (viewHolder != null) {
convertView = viewHolder.createView(LayoutInflater.from(parent.getContext()));
if (convertView != null) {
convertView.setTag(viewHolder);
}
}
} else {
viewHolder = (ViewHolderBase<T>) convertView.getTag();
}
if (viewHolder != null) {
viewHolder.setItemData(position, convertView);
viewHolder.showData(position, itemData);
}
return convertView;
}

@Override
public abstract T getItem(int position);

public abstract void update(List<T> list);

private ViewHolderBase<T> createViewHolder(int position) {
if (mViewHolderCreator == null) {
throw new RuntimeException("view holder creator is null");
}
if (mViewHolderCreator != null) {
return mViewHolderCreator.createViewHolder(position);
}
return null;
}
}
这里面我们看到,它继承了BaseAdapter,除了重写了getView,还有两个额外的方法:setViewHolderClass()和createViewHolder();setViewHolderClass就是客户端调用的方法,它里面会去创建一个ViewHolderCreator,ViewHolderCreator就可以来创建ViewHolder。当ListView调用getView()的时候,假如convertView是空,就会利用createViewHolder()去创建ViewHolder,然后用ViewHolder去创建View。假如convertView不是空,重置一下数据和position,把convertView返回出去。

(2)ViewHolderCreator.java:

public class ViewHolderCreator<T> {

private final Constructor<?> mConstructor;
private Object[] mInstanceObjects;

private ViewHolderCreator(Constructor<?> constructor, Object[] instanceObjects) {
mConstructor = constructor;
mInstanceObjects = instanceObjects;
}

public static <T> ViewHolderCreator<T> create(final Object enclosingInstance, final Class<?> cls, final Object... args) {
if (cls == null) {
throw new IllegalArgumentException("ViewHolderClass is null.");
}

// top class
boolean isEnclosingInstanceClass = false;
if (cls.getEnclosingClass() != null && !Modifier.isStatic(cls.getModifiers())) {
isEnclosingInstanceClass = true;
}

// inner instance class should pass enclosing class, so +1
int argsLen = isEnclosingInstanceClass ? args.length + 1 : args.length;

final Object[] instanceObjects = new Object[argsLen];

int copyStart = 0;
// if it is inner instance class, first argument should be the enclosing class instance
if (isEnclosingInstanceClass) {
instanceObjects[0] = enclosingInstance;
copyStart = 1;
}

// has copy construction parameters
if (args.length > 0) {
System.arraycopy(args, 0, instanceObjects, copyStart, args.length);
}

// fill the types
final Class<?>[] parameterTypes = new Class[argsLen];
for (int i = 0; i < instanceObjects.length; i++) {
parameterTypes[i] = instanceObjects[i].getClass();
}

Constructor<?> constructor = null;
try {
constructor = cls.getDeclaredConstructor(parameterTypes);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}

if (constructor == null) {
throw new IllegalArgumentException("ViewHolderClass can not be initiated");
}

return new ViewHolderCreator<T>(constructor, instanceObjects);
}

@SuppressWarnings("unchecked")
public ViewHolderBase<T> createViewHolder(int position) {
Object object = null;
try {
boolean isAccessible = mConstructor.isAccessible();
if (!isAccessible) {
mConstructor.setAccessible(true);
}
object = mConstructor.newInstance(mInstanceObjects);
if (!isAccessible) {
mConstructor.setAccessible(false);
}
} catch (Exception ex) {
ex.printStackTrace();
}
if (object == null || !(object instanceof ViewHolderBase)) {
throw new IllegalArgumentException("ViewHolderClass can not be initiated");
}
return (ViewHolderBase<T>) object;
}
}
create()方法就是利用反射得到用来创建ViewHolder的构造函数和参数,createViewHolder()反射构造出ViewHolder来。

(3)ViewHolderBase.java

public abstract class ViewHolderBase<T> {

protected int mPosition = -1;
protected View mCurrentView;

public void setItemData(int position, View view) {
mPosition = position;
mCurrentView = view;
}

/**
* create a view from resource Xml file, and hold the view that may be used in displaying data.
*/
public abstract View createView(LayoutInflater layoutInflater);

/**
* using the held views to display data
*/
public abstract void showData(int position, T itemData);

}

这个方式用起来非常的方便,它的核心是利用反射去创建ViewHolder,反射的坏处是对参数的类型要求非常严格,不过瑕不掩瑜,还是非常实用的。


智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告