gpt4 book ai didi

java - Dagger 2 范围和子组件

转载 作者:IT老高 更新时间:2023-10-28 21:05:23 28 4
gpt4 key购买 nike

我正在尝试使用 Dagger2 使我的应用程序更好,代码更易于维护我在我的项目中注入(inject)了 Dagger (听起来很有趣)。我创建了 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);
}

我可以获取组件以便注入(inject)我的Activity

    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() 方法中,我注入(inject)如下

    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 中作用域的问题。

除了 @Singleton 之外的所有内容都被 Dagger 2 忽略,对吗?我不明白组件的生命周期是如何管理的?我只有一个想法

  1. 当你使用@Singleton注解时, Dagger 是在某个静态池中创建对象,该对象会在整个应用程序生命周期中存在,当JVM进程(dalvik VM,ART)实例将被销毁时被摧毁。

  2. 当您使用任何其他注解时,只是为了让您作为开发人员更好地维护代码,@PerActivity@PerFragment 只是自定义注解而已。如果您将 @PerFragment 组件放在 Application 类中,它将与 Application 一样存在。我对吗 ?

  3. 所以我这样理解,如果 dagger 找到 @Singleton 注释,它将在第一次创建组件时添加对组件的静态引用,如果有任何其他注释,则不会持有对组件的引用。

对于上述问题的任何帮助,我将不胜感激。

更新

感谢 David Medenjak 的出色回答,我对 Dagger2 有了更深入的了解。

我也刚刚发现了问题,就我现在使用单独的 Activity 组件而言,我忘记了 ApplicationComponent 中的两行并在我的 中更改了inejction >MainActivityActivityComponent 而不是 ApplicationComponent,所以它肯定无法解析子组件的依赖关系。

 void inject(BaseActivity baseActivity);

void inject(MainAppActivity mainAppActivity);

现在一切正常,我喜欢 Dagger2 和分离的架构。

最佳答案

有点激进,但为了简化事情:所有 Scope 注释都不过是语法糖——包括 @Singleton

作用域大多只提供编译时检查。循环依赖,或关于您可能错过的事情的错误。 @Singleton 就像任何其他范围一样,唯一的区别是它是一个已经存在的注释,您不必自己创建它。您可以改用 @MySingleton

[...] dagger is creating object in some static pool that will exists during whole application lifecycle

没有。 Dagger什么都不做静态的。您有组件对象。这些组件包含由模块创建的对象。如果组件中的对象具有组件的范围,则它只会在那个确切的组件中创建一次。如果您决定创建 2 个 AppComponent 对象,您将拥有每个 @Singleton 注释对象的 2 个对象,每个对象都在其组件中。这就是为什么您应该保留对组件的引用。我见过或使用的大多数实现都将它们的 AppComponent 保留在它们的 Application 中。如果你这样做,你可以一样使用它——它仍然只是一个 POJO。

[...]you place @PerFragment component in Application class it will live as long as Application lives.

是的。如上段所述,它只是一个对象。保留引用,您保留对象。把它扔掉或创建一个新的,你就有了新的对象(在这个组件/范围内定义)。您应该将 Activity 或 fragment 范围的组件分别保留在 Activity 或 fragment 之外的任何地方,因为保留它们例如在您的应用程序组件中很可能会导致内存泄漏。 (如果不需要,您可能不需要 Activity 或 fragment 范围。)

if dagger finds @Singleton annotation it will add static reference to component when it is created first time and in case of any other annotation it won't hold reference to component.

再次,不。没有什么静态的。普通的旧 java 对象。您可以拥有多个带有自己的对象的 @Singleton 组件,但您可能不应该(尽管这是使仪器测试成为可能/容易的原因——只需交换组件。)


你提到的错误

SpiceManager cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.

这意味着您尝试注入(inject)对象的组件找不到任何方法来生成或提供 SpiceManager。确保您从 AppComponent 或其他地方提供它,没有遗漏任何注释等。

关于java - Dagger 2 范围和子组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36371716/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com