我在基类中有@inject,因此所有子类都会从基类中注入该依赖项,然后我遇到了一个问题,它说'#34;你必须明确地将它添加到'注入&#39 ;您的某个模块中的选项"。
明确地将所有子类添加到injects选项确实解决了问题,但是我需要确保每当我有一个新的子类时,我将不得不将新的子类添加到&#34;注入&#34;,或者将获得例外。有没有一种简单的方法来处理它?</ p>
谢谢!
答案 0 :(得分:1)
如果我理解正确您想要致电inject(base activity)
,但您的@Inject
注释字段在类中对基本活动进行子类化。
有一种基于反射的解决方案(可能会打破ProGuard)。此解决方案在此blog post中进行了描述。
package info.android15.dagger2example;
import java.lang.reflect.Method;
import java.util.HashMap;
public class Dagger2Helper {
private static HashMap<Class<?>, HashMap<Class<?>, Method>> methodsCache = new HashMap<>();
/**
* This method is based on https://github.com/square/mortar/blob/master/dagger2support/src/main/java/mortar/dagger2support/Dagger2.java
* file that has been released with Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ by Square, Inc.
* <p/>
* Magic method that creates a component with its dependencies set, by reflection. Relies on
* Dagger2 naming conventions.
*/
public static <T> T buildComponent(Class<T> componentClass, Object... dependencies) {
buildMethodsCache(componentClass);
String fqn = componentClass.getName();
String packageName = componentClass.getPackage().getName();
// Accounts for inner classes, ie MyApplication$Component
String simpleName = fqn.substring(packageName.length() + 1);
String generatedName = (packageName + ".Dagger" + simpleName).replace('$', '_');
try {
Class<?> generatedClass = Class.forName(generatedName);
Object builder = generatedClass.getMethod("builder").invoke(null);
for (Method method : builder.getClass().getMethods()) {
Class<?>[] params = method.getParameterTypes();
if (params.length == 1) {
Class<?> dependencyClass = params[0];
for (Object dependency : dependencies) {
if (dependencyClass.isAssignableFrom(dependency.getClass())) {
method.invoke(builder, dependency);
break;
}
}
}
}
//noinspection unchecked
return (T)builder.getClass().getMethod("build").invoke(builder);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private static <T> void buildMethodsCache(Class<T> componentClass) {
if (!Dagger2Helper.methodsCache.containsKey(componentClass)) {
HashMap<Class<?>, Method> methods = new HashMap<>();
for (Method method : componentClass.getMethods()) {
Class<?>[] params = method.getParameterTypes();
if (params.length == 1)
methods.put(params[0], method);
}
Dagger2Helper.methodsCache.put(componentClass, methods);
}
}
public static void inject(Class<?> componentClass, Object component, Object target) {
HashMap<Class<?>, Method> methods = methodsCache.get(componentClass);
if (methods == null)
throw new RuntimeException("Component " + componentClass + " has not been built with " + Dagger2Helper.class);
Class targetClass = target.getClass();
Method method = methods.get(targetClass);
if (method == null)
throw new RuntimeException("Method for " + targetClass + " injection does not exist in " + componentClass);
try {
method.invoke(component, target);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}
然后在你的基础活动中你可以这样做:
Dagger2Helper.inject(AppComponent.class, component, this);
我不认为一点反思会对性能造成太大影响,对我而言,真正的问题是打破ProGuard。