package in.srain.cube.views.list;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class LazyViewHolderCreator<T> implements ViewHolderCreator<T> {
private final Constructor<?> mConstructor;
private Object[] mInstanceObjects;
private LazyViewHolderCreator(Constructor<?> constructor, Object[] instanceObjects) {
mConstructor = constructor;
mInstanceObjects = instanceObjects;
}
public static <ItemDataType> ViewHolderCreator<ItemDataType> 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");
}
ViewHolderCreator lazyCreator = new LazyViewHolderCreator(constructor, instanceObjects);
return lazyCreator;
}
@Override
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;
}
}