匕首2:无法在其他范围内注入单身人士

时间:2016-03-13 15:44:07

标签: android dagger-2

我有Singleton作用域模块,提供一些标准单例:应用程序,数据库服务等。 但是对于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()

以下是我的应用程序模块的片段:

@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;
    }
}

这里是活动模块和组件:

@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);
}

我做错了什么?

3 个答案:

答案 0 :(得分:11)

  

我做错了什么?

此:

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

您只能在组件中包含使用相同作用域的未作用域或模块。您将需要使用多个组件。

要包含应用程序中的依赖项,您需要将它们放在不同的组件中,例如: ApplicationComponent。如果您执行此操作,则有两个选项:将SplashComponent声明为SubComponent ApplicationComponent或将ApplicationComponent添加为组件的依赖关系。如果将其添加为依赖项,请务必在ApplicationComponent中提供方法,以便它可以访问依赖项。

e.g。如果您要使用组件依赖项:

@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
}

答案 1 :(得分:10)

我想从我的理解中解释Dagger 2的一些关键点。

主要演员:

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

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

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

它是如何运作的?

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

void inject(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);
  }

好吧...... enter image description here

您可以将未绑定的和(Singleton和PerService)作用域对象注入SyncService.class

答案 2 :(得分:0)

作用域规则:

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

在这种情况下,组件还涉及子组件。

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

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