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看出来跟普通的ListView的Adapter的使用唯一的区别是多了一步setViewHolderClass,其他的没有任何区别。
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());
}
2.看下具体的实现
(1)ListViewDataAdapter.java
public class ListViewDataAdapter<T> extends ListViewDataAdapterBase<T> {它继承了ListViewDataAdapterBase,里面全是对数据的操作。转载请标明出处:http://blog.csdn.net/goldenfish1919/article/details/47039985
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;
}
}
(2)PersonViewHolder.java
public class PersonViewHolder extends ViewHolderBase<Person>{可以看到,这里面全是对view的操作。通过这种方式,起到了很好的分离数据与View的效果,代码变得更整洁,看起来赏心悦目。以后,在书写Adapter的时候,只需要写ViewHolder就可以,ListViewDataAdapter大部分时候都不要做任何改动,需要改的时候只要继承这个类就可以了,大大的减少了工作量。
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();
}
});
}
}
看些是如何来实现的:
(1)ListViewDataAdapterBase:
public abstract class ListViewDataAdapterBase<T> extends BaseAdapter {这里面我们看到,它继承了BaseAdapter,除了重写了getView,还有两个额外的方法:setViewHolderClass()和createViewHolder();setViewHolderClass就是客户端调用的方法,它里面会去创建一个ViewHolderCreator,ViewHolderCreator就可以来创建ViewHolder。当ListView调用getView()的时候,假如convertView是空,就会利用createViewHolder()去创建ViewHolder,然后用ViewHolder去创建View。假如convertView不是空,重置一下数据和position,把convertView返回出去。
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;
}
}
(2)ViewHolderCreator.java:
public class ViewHolderCreator<T> {create()方法就是利用反射得到用来创建ViewHolder的构造函数和参数,createViewHolder()反射构造出ViewHolder来。
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;
}
}
(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,反射的坏处是对参数的类型要求非常严格,不过瑕不掩瑜,还是非常实用的。
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。