Ricardo's Blog

  • 03:43:16 pm on January 19, 2011 | 3
    Tags: , ,

    The Problem: Adapters cannot be injected into Activities because the BaseAdapter constructor requires a Context be passed to it.

    The Solution: Create a new Guice @InjectAdapter annotation and TypeListener that dynamically creates an adapter on injection, passing the inject Activity to the adapter’s constructor.

    So, our activity code might look something like this:

    public class SampleActivity extends GuiceListActivity {
     List<Integer> items;
     public void setListAdapter(ListAdapter adapter) {
     public void onCreate(Bundle savedInstanceState) {
      Log.i(TAG, "searching for local profiles");

    Out module might then have the following code:

    bindListener(Matchers.any(), new AdapterTypeListener(binder()));

    Where AdapterTypeListener is defined as follows:

    public <T> void hear(TypeLiteral<T> typeLiteral, TypeEncounter<T> typeEncounter) {
    Class<T> type = typeLiteral.getRawType();
    for (Field field : type.getDeclaredFields()) {
    	if (Adapter.class.isAssignableFrom(field.getType()) && field.isAnnotationPresent(InjectAdapter.class)) {
    		typeEncounter.register(new AdapterMembersInjector<T>(field));
    for (Method method : type.getDeclaredMethods()) {
    	if(method.isAnnotationPresent(InjectAdapter.class)) {
    		typeEncounter.register(new AdapterMembersInjector<T>(method));

    Last we could define AdapterMembersInjector as follows:

    public class AdapterMembersInjector<T> implements MembersInjector<T> {
    	private Field field;
    	private Method setter;
    	TypeEncounter<T> typeEncounter;
    	AdapterMembersInjector(Field field, TypeEncounter<T> typeEncounter) {
    		this.field = field;
    	AdapterMembersInjector(Method setter, TypeEncounter<T> typeEncounter) {
    		this.setter = setter;
    	public void injectMembers(T activity) {
    		Adapter adapter;
    		if(field != null) {
    			try {
    				field.set(activity, adapter);
    			} catch (IllegalAccessException e) {
    				throw new RuntimeException(e);
    		} else if(setter != null) {
    			try {
    				setter.invoke(activity, adapter);
    			} catch (IllegalArgumentException e) {
    				throw new RuntimeException(e);
    			} catch (IllegalAccessException e) {
    				throw new RuntimeException(e);
    			} catch (InvocationTargetException e) {
    				throw new RuntimeException(e);

    The problem is how do we create a reference to Adapter in the above MembersInjector, with all the correct dependencies including the Activity context injected into it’s constructor?



Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: