我正在尝试使用Dagger2
让我的应用更好,代码更易于维护我抓住了一般的想法,但仍无法弄清楚范围是如何由Dagger2
管理的
我在我的项目中注入了匕首(听起来很有趣)。
我创建了ApplicationComonent
组件,它在我的项目中完美运行。
这是我的代码。
@Singleton
@Component(modules = {
ApplicationModule.class,
ThreadingModule.class,
NetworkModule.class,
DatabaseModule.class,
ServiceModule.class,
ParseModule.class,
PreferencesSessionModule.class})
public interface ApplicationComponent {
ActivityComponent activityComponent(ActivityModule activityModule);
void inject(BaseActivity baseActivity);
void inject(MainAppActivity mainAppActivity);
void inject(MyApplication application);
void inject(BaseFragment baseFragment);
void inject(MyService service);
void inject(RegistrationIntentService service);
}
我在MyApplication
类中创建我的组件实例,就像这样
private void initializeAndInjectComponent() {
mApplicationComponent =
DaggerApplicationComponent
.builder()
.threadingModule(new ThreadingModule(1))
.applicationModule(new ApplicationModule(this))
.networkModule(new NetworkModule(
MyService.API_SERVER_BASE_URL,
MyService.TIMEOUT))
.build();
mApplicationComponent.inject(this);
}
我可以获取组件以便注入我的Activities
MyApplication application = MyApplication.get(this);
application.getApplicationComponent().inject(this);
一切都很完美。
添加每个方法以及模块类都使用@Singleton
范围进行注释,所有模块都与ApplicationComponent
现在我想更好地建立依赖关系,我已经看到很多自定义范围的示例,例如@PerActivity
,@PerFragment
。我有很多问题,但稍后会这样。
所以我创建了ActivityComponent
@PerActivity
@Subcomponent(
modules = {
NetworkServiceModule.class,
ActivityModule.class,
PermissionModule.class
})
public interface ActivityComponent {
Activity activity();
void inject(BaseActivity baseActivity);
}
所有模块都是这样的
@PerActivity
@Module
public class ActivityModule {
private Activity mActivity;
public ActivityModule(Activity activity) {
this.mActivity = activity;
}
@Provides
@PerActivity
Activity provideActivity() {
return this.mActivity;
}
}
我的BaseActivity
// Dependencies from ApplicationComponent
@Inject
protected ApplicationSettingsManager mApplicationSettingsManager;
@Inject
protected ScheduledThreadPoolExecutor mPoolExecutor;
// Dependencies from ActivityComponent
@Inject
protected SpiceManager mSpiceManager;
@Inject
protected PermissionController mPermissionController;
在我的onCreate()
方法中,我注入了以下内容
MyApplication application = MyApplication.get(this);
application.getApplicationComponent().activityComponent(new ActivityModule(this)).inject(this);
在创建子组件ActivityComponent
之前,它是
MyApplication application = MyApplication.get(this);
application.getApplicationComponent().inject(this);
现在我收到了错误
Error:(34, 10) error: com.octo.android.robospice.SpiceManager cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
BaseActivity.mSpiceManager
[injected field of type: com.octo.android.robospice.SpiceManager mSpiceManager]
我无法弄清楚问题在哪里,我错过了什么。 我对dagger2中的范围有疑问。
Dagger 2忽略了@Singleton
以外的所有内容,我是对的吗?
我不明白组件的生命是如何管理的?我只有一个想法
当您使用@Singleton
注释时,dagger会在整个应用程序生命周期中存在的某个静态池中创建对象,并且在销毁JVM进程(dalvik VM,ART)实例时将被销毁。
当您使用任何其他注释时,您只需为开发人员更好地维护代码,@PerActivity
,@PerFragment
只是自定义注释。如果您在Application类中放置@PerFragment
组件,只要应用程序存在,它就会存在。我对吗 ?
所以我理解这一点,如果dagger找到@Singleton
注释,它将在第一次创建时添加对组件的静态引用,如果是任何其他注释,它将不会保留对组件的引用
我非常感谢上述问题的任何帮助。
更新
感谢David Medenjak
获得了很好的答案,我对Dagger2
有了更深入的了解。
我刚刚发现了问题,就我现在使用单独的Activity
组件而言,我忘记了ApplicationComponent
中的两行并将MainActivity
中的inejction更改为{{ 1}}而不是ActivityComponent
,所以肯定它无法解析子组件的依赖关系。
ApplicationComponent
现在一切都很完美,我喜欢 void inject(BaseActivity baseActivity);
void inject(MainAppActivity mainAppActivity);
和分离的架构。
答案 0 :(得分:60)
有点激进,但为了简化事情:
所有范围注释都只是语法糖 - 包括@Singleton
。
范围主要是提供编译时间检查。循环依赖关系,或者您可能错过的事情的错误。 @Singleton
就像任何其他范围一样,唯一的区别是它是一个已经存在的注释,您不必自己创建它。您可以改为使用@MySingleton
。
[...] dagger在整个应用程序生命周期中存在的某个静态池中创建对象
没有。 Dagger没有没有静态。你有组件对象。这些组件包含由模块创建的对象。如果组件中的对象具有组件的范围,则只会在中创建一个组件。如果您决定创建2个AppComponent
个对象,则每个@Singleton
注释对象将包含2个对象,每个对象位于其组件中。这就是为什么你应该保留对组件的引用。我见过或使用的大多数实现因此将AppComponent
保留在Application
内。如果你这样做,你可以使用喜欢一个单身 - 它仍然只是一个POJO。
[...]你将@PerFragment组件放在Application类中,只要应用程序存在,它就会存在。
是。如上段所述,它只是一个对象。保留参考,保留对象。扔掉它或创建一个新的对象(在此组件/范围内定义)。尽管不分别在活动或片段之外的任何地方保留活动或片段范围组件,但应保留它们,例如在您的应用程序组件中很可能会导致内存泄漏。 (如果它没有,你可能不需要活动或片段范围。)
如果dagger找到
@Singleton
注释,它将在第一次创建时添加对组件的静态引用,如果是任何其他注释,它将不会保留对组件的引用。
再一次,没有。没什么是静止的。普通的旧java对象。您可以将多个@Singleton
组件与自己的对象组合在一起,但您可能不应该这样做(尽管这使得仪器测试变得可行/简单 - 只需交换组件。)
如果没有@Inject构造函数或@ Provide-或@ Produces-annotated方法,则无法提供SpiceManager。
这意味着您尝试注入对象的组件无法找到生成或提供SpiceManager
的任何方法。确保您从AppComponent或其他地方提供,不遗漏任何注释等。