package com.android.pc.ioc.adapter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Map;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.android.pc.ioc.app.Ioc;
import com.android.pc.ioc.image.ImageDownloader;
import com.android.pc.ioc.image.Utils;
import com.android.pc.ioc.inject.InjectBinder;
import com.android.pc.ioc.inject.InjectView;
import com.android.pc.ioc.util.ContextUtils;
import com.android.pc.ioc.view.listener.OnListener;
/**
* <h1>全自动化适配器</h1>
* T1为适配器的数据集合类型<br>
* T2为适配器的ViewHolder<br>
* 无需手动去绑定 适用于不太复杂的适配器
* @author gdpancheng@gmail.com 2014-5-20 上午12:18:05
*/
public class LazyAdapter<T1, T2> extends BaseAdapter {
private ArrayList<T1> dataList;
private int layout_id = -1;
private LayoutInflater layoutInflater;
private Constructor<?> constructor;
private Class<?> clazz;
private String packageName;
private Context context;
ImageDownloader imageDownloader = null;
@SuppressWarnings("unchecked")
public LazyAdapter(ListView listView, ArrayList<T1> dataList, int layout_id) {
this.dataList = dataList;
this.layout_id = layout_id;
this.context = listView.getContext();
this.layoutInflater = LayoutInflater.from(context);
this.packageName = Ioc.getIoc().getApplication().getPackageName();
imageDownloader = new ImageDownloader(context, 0);
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int scrollState) {
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
if (!Utils.hasHoneycomb()) {
imageDownloader.setPauseWork(true);
}
} else {
imageDownloader.setPauseWork(false);
}
}
@Override
public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass();
Type[] types = parameterizedType.getActualTypeArguments();
try {
Constructor<?>[] constructors = ((Class<T2>) types[1]).getConstructors();
if (constructors.length > 0) {
constructor = constructors[0];
}
} catch (Exception e) {
e.printStackTrace();
}
}
public ImageDownloader getImageDownloader() {
return imageDownloader;
}
public void setImageDownloader(ImageDownloader imageDownloader) {
this.imageDownloader = imageDownloader;
}
@Override
public int getCount() {
clazz = dataList.size() > 0 ? dataList.get(0).getClass() : null;
return dataList.size();
}
@Override
public Object getItem(int arg0) {
return dataList.get(arg0);
}
@Override
public long getItemId(int arg0) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup arg2) {
try {
Object viewHold = null;
if (convertView == null) {
convertView = layoutInflater.inflate(layout_id, null);
try {
viewHold = constructor.newInstance(this);
} catch (Exception e) {
viewHold = constructor.newInstance(context);
}
// -------------------------------------------------------
setView(viewHold, convertView, position);
// 缓存绑定
convertView.setTag(viewHold);
} else {
viewHold = convertView.getTag();
}
// -------------------------------------------------------
// 绑定数据
deal(dataList.get(position), (T2) viewHold, position);
} catch (Exception e) {
e.printStackTrace();
}
return convertView;
}
public void deal(T1 data, T2 viewHold, int position) {
injectAdapter(viewHold, position);
};
/**
* adapter里面使用 自动去注入组件
* @author gdpancheng@gmail.com 2013-10-22 下午12:59:07
* @param object
* @param view
* @return void
*/
public void injectAdapter(Object view, int position) {
String data;
Field[] fields = view.getClass().getDeclaredFields();
if (fields != null && fields.length > 0) {
for (Field field : fields) {
InjectView v = field.getAnnotation(InjectView.class);
if (v == null) {
continue;
}
data = getString(position, field.getName());
if (data == null) {
continue;
}
try {
field.setAccessible(true);
Object object = field.get(view);
if (object == null || !View.class.isAssignableFrom(object.getClass())) {
continue;
}
((View)object).setTag(position);
if (TextView.class.isAssignableFrom(object.getClass())) {
((TextView) object).setText(data);
}
if (ImageView.class.isAssignableFrom(object.getClass())) {
download(((ImageView) object), data);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private void setView(Object viewHold, View view, int postion) {
try {
Field[] fields = viewHold.getClass().getDeclaredFields();
if (fields != null && fields.length > 0) {
for (Field field : fields) {
field.setAccessible(true);
InjectView vs = field.getAnnotation(InjectView.class);
if (vs == null) {
continue;
}
View v;
if (vs.value()!=ContextUtils.ID_NONE) {
v = view.findViewById(vs.value());
}else {
v = view.findViewById(Ioc.getIoc().getApplication().getResources().getIdentifier(field.getName(), "id", this.packageName));
}
if (v == null) {
Ioc.getIoc().getLogger().e("变量 "+field+" 无法赋值,请检查ID和NAME");
continue;
}
try {
if (View.class.isAssignableFrom(v.getClass())) {
field.set(viewHold, v);
}
} catch (Exception e) {
e.printStackTrace();
}
InjectBinder[] binders = vs.binders();
if (binders == null) {
continue;
}
for (int i = 0; i < binders.length; i++) {
InjectBinder injectBinder = binders[i];
Class<? extends OnListener>[] clazzes = injectBinder.listeners();
for (Class<? extends OnListener> clazz : clazzes) {
try {
OnListener listener = clazz.newInstance();
listener.listener(v, viewHold, injectBinder.method());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 异步图片下载接口
* @author gdpancheng@gmail.com 2012-12-3 下午4:25:58
*/
public void download(ImageView view, String url) {
imageDownloader.loadImage(url, view);
};
private String getString(int postion, String name) {
Object object = dataList.get(postion);
if (Map.class.isAssignableFrom(clazz)) {
return ((Map<?, ?>) object).containsKey(name) ? ((Map<?, ?>) object).get(name).toString() : "";
} else {
try {
Method readName = clazz.getDeclaredMethod("get" + Character.toUpperCase(name.charAt(0)) + name.substring(1));
return readName.invoke(object).toString();
} catch (Exception e) {
return null;
}
}
}
}