Skip to content

Instantly share code, notes, and snippets.

@castorflex
Last active August 4, 2017 13:43
Show Gist options
  • Save castorflex/5776863 to your computer and use it in GitHub Desktop.
Save castorflex/5776863 to your computer and use it in GitHub Desktop.
Make your multiple type view adapter with annotations! Gist for http://castorflex.github.io/blog/2013/06/11/making-a-multiple-view-type-adapter-with-annotations/

Make your multiple type view adapter with annotations!

Gist for Making a Multiple View Types Adapter With Annotations

Pretty easy to use.

  1. Create your delegate adapters, implementing DelegateAdapter, and with the annotation DelegateAdapterType. e.g:
@DelegateAdapterType(itemType = 0)
public class SimpleTextDelegateAdapter implements DelegateAdapter { ... getView() ... }
  1. Your main adapter have to extend the DispatcherAdapter. You will have to override getItemViewType add your delegateAdapters in the DelegateAdaptersAnnotation just like this:
@DelegateAdapters(delegateAdapters = {
  	SimpleTextDelegateAdapter.class,
		HtmliTextDelegateAdapter.class,
		GalleryDelegateAdapter.class
}) 
public class MyAdapter extends DispatcherAdapter{ ... }
  1. You're done!

You can improve this gist/lib. We can imagine for example a wrapper class containing all the delegates, and an annotation DelegateAdapterWrapper(Class) for the DispatcherAdapter, so we only pass one the wrapper as parameter. Then if you have to add a new view type for your list, the only thing you have to do is add it in the wrapper class! Pretty handy no?

/**
* You have to implement this interface for your delegates.
*/
public interface DelegateAdapter {
public View getView(int position, View convertView, ViewGroup parent, LayoutInflater inflater, Object item);
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DelegateAdaptersAnnotation {
Class<? extends DelegateAdapter>[] delegateAdapters();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DelegateAdapterType {
long itemType();
}
/**
* Your custom adapter should extends this class
*/
public abstract class DispatcherAdapter extends BaseAdapter {
private LongSparseArray<DelegateAdapter> mDelegateAdapterSparseArray;
protected Context mContext;
protected LayoutInflater mLayoutInflater;
public DispatcherAdapter(Context context) {
mContext = context;
mLayoutInflater = LayoutInflater.from(context);
initDelegates();
}
/**
* Init the delegates here, with reflection
*/
private void initDelegates() {
mDelegateAdapterSparseArray = new LongSparseArray<DelegateAdapter>();
DelegateAdaptersAnnotation annotation = getClass().getAnnotation(DelegateAdaptersAnnotation.class);
if (annotation != null) {
Class[] clazzs = annotation.delegateAdapters();
if (clazzs != null) {
for (Class<?> clazz : clazzs) {
if (!DelegateAdapter.class.isAssignableFrom(clazz)) {
throw new RuntimeException("The class " + clazz.getName() + " is not a subclass of " + DelegateAdapter.class.getName());
}
DelegateAdapterType delegateAdapterType = clazz.getAnnotation(DelegateAdapterType.class);
if(delegateAdapterType == null){
throw new RuntimeException("The class "+clazz.getName()+" should have the annotation DelegateAdapterField");
}
long itemtype = delegateAdapterType.itemType();
if(mDelegateAdapterSparseArray.get(itemtype) != null){
throw new RuntimeException("The item type "+itemtype+" is already defined!");
}
DelegateAdapter adapter = null;
try {
adapter = (DelegateAdapter) clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException("Error while instanciating "+clazz.getName()+" with default constructor: "+e.getMessage(), e);
}
mDelegateAdapterSparseArray.put(itemtype, adapter);
}
}
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
long itemtype = getItemViewType(position);
DelegateAdapter delegateAdapter = mDelegateAdapterSparseArray.get(itemtype);
if(delegateAdapter == null){
throw new RuntimeException("Unknown type "+itemtype+" called");
}
return mDelegateAdapterSparseArray.get(itemtype).getView(position, convertView, parent, mLayoutInflater, getItem(position));
}
@Override
public int getViewTypeCount() {
return mDelegateAdapterSparseArray.size();
}
}
@IRMobydick
Copy link

can you make a working example of this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment