以Activity为例。我有一个BaseActivity,每个Activity都是从它继承而来的。有没有一种方法可以只在组件中为BaseActivity创建一个inject方法,在BaseActivity的onCreate方法中调用inject,然后子活动中的@Inject字段自动被注入?
我遇到了相同的情况。缓解在所有活动中从共同组件中注入的压力的一种方法如下:
1)扩展Application类以能够创建共同组件并保留对其的引用。
public class ApplicationDagger extends Application {
private ApplicationComponent component;
@Override
public void onCreate(){
super.onCreate();
component = DaggerApplicationComponent.builder().applicationModule(new ApplicationModule(this)).build();
}
public ApplicationComponent getComponent(){
return component;
}
}
2)创建一个抽象的DaggerActivity,它从应用程序中获取公共组件,并调用一个抽象方法injectActivity
,并将该组件作为参数传递。像这样:
public abstract class DaggerActivity extends Activity {
@Override
public void onCreate(Bundle saved){
super.onCreate(saved);
ApplicationComponent component = ((ApplicationDagger) getApplication()).getComponent();
injectActivity(component);
}
public abstract void injectActivity(ApplicationComponent component);
}
3) 最后,您需要实际注入每个扩展DaggerActivity
的Activity
。 但是现在可以用更少的工作完成这项工作,因为您必须实现abstract
方法,否则将出现编译错误。 在这里我们来看一下:
public class FirstActivity extends DaggerActivity {
@Inject
ClassToInject object;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//initialize your Activity
}
@Override
public void injectActivity(ApplicationComponent component) {
component.inject(this);
}
}
当然,你仍然需要在组件中显式声明每个Activity。
更新:将@ActivityScope对象注入到Fragment中
在某些情况下,我需要使用自定义作用域将对象绑定到Activity
生命周期。我决定扩展这篇文章,因为它可能会帮助一些人。
假设你有一个@Module类ActivityModule
和一个@Subcomponent接口ActivityComponent
。
你需要修改DaggerActivity
。继承DaggerActivity
的Activities
需要实现新的方法(更改签名)。
public abstract class ActivityDagger extends AppCompatActivity {
ActivityComponent component;
@Override
protected void onCreate(Bundle savedInstanceState) {
component = ((ApplicationDagger) getApplication()).getComponent().plus(new ActivityModule(this));
injectActivity(component);
super.onCreate(savedInstanceState);
}
ActivityComponent getComponent() {
return component;
}
public abstract void injectActivity(ActivityComponent component);
}
那么,可以像这样创建一个扩展Fragment
的类FragmentDagger
:
public abstract class FragmentDagger extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityDagger activityDagger = (ActivityDagger) getActivity();
ActivityComponent component = activityDagger.getComponent();
injectFragment(component);
}
public abstract void injectFragment(ActivityComponent component);
}
关于 Activities
,扩展自FragmentDagger
的Fragments
只需要实现一个方法:
public abstract void injectFragment(ActivityComponent component);
你应该可以在任何地方重复使用Fragments
。请注意,在创建组件后,应在ActivityDagger
中调用 super.onCreated()
方法。否则,在重新创建Activity
状态时,会出现空指针异常,因为将调用Fragment
的super.onCreate()
方法。
public class UiInjector {
private static final String METHOD_NAME = "inject";
private final UIComponent component;
public UiInjector(final UIComponent component) {
this.component = component;
}
public void inject(final Object subject) {
try {
component.getClass()
.getMethod(METHOD_NAME, subject.getClass())
.invoke(component, subject);
} catch (final NoSuchMethodException exception) {
throwNoInjectMethodForType(component, subject.getClass());
} catch (final Exception exception) {
throwUnknownInjectionError(exception);
}
}
private void throwNoInjectMethodForType(final Object component, final Class subjectType) {
throw new RuntimeException(component.getClass().getSimpleName() +
" doesn't have inject method with parameter type : " + subjectType);
}
private void throwUnknownInjectionError(final Exception cause) {
throw new RuntimeException("Unknown injection error", cause);
}
}
-keep class <ComponentClass> { *; }
到您的规则中,以保留组件中的注入方法。