【问题标题】:Dagger 2: Unable to inject singleton in other scopeDagger 2:无法在其他范围内注入单例
【发布时间】:2016-06-28 14:09:45
【问题描述】:

我有提供一些标准单例的单例范围模块:应用程序、数据库服务等。 但是对于 Activity,我有单独的模块应该为他的 Activity 创建 Presenter,我需要将 Application 上下文传递给它。但是在尝试编译项目时出现以下错误:

Error:(13, 1) error: xxx.SplashComponent scoped with @xxx.ViewScope may not reference bindings with different scopes:
@Provides @Singleton xxx.ApplicationModule.provideAppContext()

这是我的应用程序模块的 sn-p:

@Singleton
@Module
public class ApplicationModule {

    private Application app;

    public ApplicationModule(Application app) {
        this.app = app;
    }

    @Provides
    @Singleton
    @Named("ui")
    Scheduler provideUIScheduler() {
        return AndroidSchedulers.mainThread();
    }

    @Provides
    @Singleton
    @Named("io")
    Scheduler provideIOScheduler() {
        return Schedulers.io();
    }

    @Provides
    @Singleton
    Application provideApplication() {
        return app;
    }

    @Provides
    @Singleton
    Context provideAppContext() {
        return app;
    }
}

这里是 Activity 模块和组件:

@Module
public class SplashModule {
    private final FragmentManager fragmentManager;

    public SplashModule(FragmentManager fragmentManager) {

        this.fragmentManager = fragmentManager;
    }

    @Provides
    @ViewScope
    Presenter getPresenter(Context context) {
        return new SplashPresenter(context, fragmentManager);
    }
}

组件:

@ViewScope
@Component(modules = {SplashModule.class, ApplicationModule.class})
public interface SplashComponent {
    void inject(SplashActivity activity);
}

我做错了什么?

【问题讨论】:

  • 谢谢。查看您的错误消息后,我了解到我的模块文件包含具有不同范围的方法。比如“@FirstScope@Binds Class1 method1()”和“@SecondScope@Binds Class2 method2()”。

标签: android dagger-2


【解决方案1】:

我做错了什么?

这个:

@ViewScope
@Component(modules = {SplashModule.class /*View scoped*/,
    ApplicationModule.class/*Singleton scoped*/})

您只能在组件中包含无范围的或具有相同范围的模块。您将需要使用多个组件。

要包含应用程序的依赖项,您需要将它们放在不同的组件中,例如ApplicationComponent。如果你这样做,你有 2 个选择:要么将 SplashComponent 声明为 ApplicationComponentSubComponent,要么将 ApplicationComponent 添加为组件的依赖项。如果您将其添加为依赖项,请确保在您的ApplicationComponent 中也提供方法,以便它可以访问依赖项。

例如如果您要使用组件依赖项:

@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {

    void inject(MyApplication app);

    // todo: also add getters for your other dependencies you need further down the graph
    Application getApplication();

}

@Component(modules = {SplashModule.class}, dependencies={ApplicationComponent.class})
public interface SplashComponent {
    // as before
}

【讨论】:

  • 还是看不懂
【解决方案2】:

我想根据我的理解来解释一下匕首2的一些关键点。

主要演员:

  • “组件”是模块和发生注入的地方之间的桥梁。

  • “模块”是我们声明将被注入的对象的地方。

  • “范围”就像相关注入故事的生命周期。

它是如何工作的?

  • 用范围声明组件(“Singleton”)。
  • 定义可以在组件的模块列表中注入所需对象的模块。

void 注入(BaseFragment baseFragment);

**********将组件模块中提供的对象暴露给子组件****
dbHelper dbHelper();

  • 声明模块并提供要通过组件注入的对象。

例如:

@Singleton 
@Component(modules = { ApplicationModule.class, NetworkModule.class })
public interface ApplicationComponent {

  void inject(BaseActivity baseActivity);
  DbHelper dbHelper();
}




@PerService @Component(dependencies = ApplicationComponent.class, modules = ServiceModule.class)
public interface ServiceComponent {

  void inject(SyncService service);

}

// SyncService.java

  @Inject DbHelper dbHelper;  (even Singleton scoped)

  private void setupInjector() {
    ServiceComponent mServiceComponent = DaggerServiceComponent.builder()
        .applicationComponent(getApplicationComponent())
        .serviceModule(new ServiceModule(this))
        .build();
    mServiceComponent.inject(this);
  }

好吧...

您可以将无范围和(Singleton 和 PerService)范围的对象注入到您的 SyncService.class

【讨论】:

  • 暴露像DbHelper dbHelper() 这样的东西是我一直想念的。非常感谢这个答案。
  • 我必须纠正你一点关于“单例是默认设置”的问题。 No-scope 是默认的,不是 Singleton。如果没有 @Singleton,每次注入都会有一个新实例。
  • @WindRider 你是对的。这就是为什么我们将一些组件标记为 Singleton 以避免每次都创建昂贵的对象。
  • 其实每次注入都会创建,所以它的有效作用域其实就是消费者的作用域。
  • 消费者的范围是什么意思?
【解决方案3】:

范围规则:

  • 当一个类型被标记了范围注释时,它只能被具有相同范围注释的组件使用。
  • 当一个组件被标记了范围注解时,它只能提供带有该注解的类型或没有注解的类型。
  • 子组件不能使用其父组件之一使用的范围注释。

组件还涉及此上下文中的子组件。

注意:- 使用范围注解的模块只能在使用相同范围注解的组件中使用。 Check Here

有关 Android 中 Dagger 的更多信息,请访问 this training 并练习 it here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多