Dagger 2 injection with inheritance
/** | |
* This class allows to inject into objects through a base class, | |
* so we don't have to repeat injection code everywhere. | |
* | |
* The performance drawback is about 0.013 ms per injection on a very slow device, | |
* which is negligible in most cases. | |
* | |
* Example: | |
* <pre>{@code | |
* Component { | |
* void inject(B b); | |
* } | |
* | |
* class A { | |
* void onCreate() { | |
* componentReflectionInjector.inject(this); | |
* } | |
* } | |
* | |
* class B extends A { | |
* @Inject MyDependency dependency; | |
* } | |
* | |
* new B().onCreate() // dependency will be injected at this point | |
* | |
* class C extends B { | |
* | |
* } | |
* | |
* new C().onCreate() // dependency will be injected at this point as well | |
* }</pre> | |
* | |
* @param <T> a type of dagger 2 component. | |
*/ | |
public final class ComponentReflectionInjector<T> implements Injector { | |
private final Class<T> componentClass; | |
private final T component; | |
private final HashMap<Class<?>, Method> methods; | |
public ComponentReflectionInjector(Class<T> componentClass, T component) { | |
this.componentClass = componentClass; | |
this.component = component; | |
this.methods = getMethods(componentClass); | |
} | |
public T getComponent() { | |
return component; | |
} | |
@Override | |
public void inject(Object target) { | |
Class targetClass = target.getClass(); | |
Method method = methods.get(targetClass); | |
while (method == null && targetClass != null) { | |
targetClass = targetClass.getSuperclass(); | |
method = methods.get(targetClass); | |
} | |
if (method == null) | |
throw new RuntimeException(String.format("No %s injecting method exists in %s component", target.getClass(), componentClass)); | |
try { | |
method.invoke(component, target); | |
} | |
catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
private static final ConcurrentHashMap<Class<?>, HashMap<Class<?>, Method>> cache = new ConcurrentHashMap<>(); | |
private static HashMap<Class<?>, Method> getMethods(Class componentClass) { | |
HashMap<Class<?>, Method> methods = cache.get(componentClass); | |
if (methods == null) { | |
synchronized (cache) { | |
methods = cache.get(componentClass); | |
if (methods == null) { | |
methods = new HashMap<>(); | |
for (Method method : componentClass.getMethods()) { | |
Class<?>[] params = method.getParameterTypes(); | |
if (params.length == 1) | |
methods.put(params[0], method); | |
} | |
cache.put(componentClass, methods); | |
} | |
} | |
} | |
return methods; | |
} | |
} |
This comment has been minimized.
This comment has been minimized.
This is a proguard-friendly solution. |
This comment has been minimized.
This comment has been minimized.
You are right, sorry |
This comment has been minimized.
This comment has been minimized.
Can't get how to use it, do you have some examples? |
This comment has been minimized.
This comment has been minimized.
Seems not working if Proguard is enabled, any idea? |
This comment has been minimized.
This comment has been minimized.
I also encountered problem with Dagger 2 and don't know why. In my case it seems that inject(presenter) methods in component are not preserved as they are not called directly in code but only via reflection. I have dontoptimize setting enabled so Proguard should not strip them but it is. |
This comment has been minimized.
This comment has been minimized.
Does it have any ProGuard requirements? Seems elegant solution but I'm afraid of ProGuard. |
This comment has been minimized.
This comment has been minimized.
You need to tell proguard to keep the Dagger2 Components:
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
And you will lost most valuable benefit of dagger 2 - proguard without headache.