Dagger - 在不同的组件上获取相同的实例

时间:2017-03-22 13:41:10

标签: android dagger-2

我遇到类似this问题中的类似问题。 虽然接受的答案确实有帮助,但我缺少最后一块来解决问题。

我有2个Android库模块:commonexp,它取决于common

common下的所有内容:

@Module
public class CommonModule {
    @Singleton
    @Provides
    public Repository providesRepository() {
        return new Repository();
    }
}

@Singleton
@Component(modules={CommonModule.class})
public interface CommonComponent {
    void inject(CommonClass commonClass);
    /**
        CommonClass needs instance of Repository
    **/
}

public class CommonDIHolder {
    public static CommonComponent sComponent;

    public static void init() {
        sComponent = DaggerCommonComponent.builder().build();
    }
}

exp下的所有内容:

@Module(includes={CommonModule.class})
public class ExpModule {
    @Singleton
    @Provides
    public ExpResource provideExpResource() {
        return new ExpResource();
    }
}

@Singleton
@Component(modules={ExpModule.class}, dependencies={CommonComponent.class})
public interface ExpComponent {
    void inject(ExpClass expClass); 
    /**
        ExpClass needs instance of Repository and ExpResource
    **/
}

public class ExpDIHolder {
    public static ExpComponent sComponent;

    public static void init() {
        sComponent = DaggerExpComponent.builder()
                            .commonComponent(CommonDIHolder.sComponent)
                            .build();
    }
}

我需要CommonClassExpClass同时收到Repository的同一个实例。

此方法存在的问题是@Singleton无法取决于@Singleton。所以我必须将ExpComponent的范围更改为名为@ExpScope的自定义范围。然后我也将provideExpResource更改为@ExpScope

然后我遇到一个错误,指出ExpComponent可能不会引用具有不同范围的绑定。它指的是provideRepository,它具有不同的范围(@Singleton)。如果我将范围更改为ExpScope,那么CommonComponent将与provideRepository具有不同的范围。

如果我将所有@Singleton更改为@ExpScope,则会收到以下错误消息:depends on scoped components in a non-hierarchical scope ordering

我该怎么办?或者我在这里做错了吗?

1 个答案:

答案 0 :(得分:1)

仅使用一个@Singleton范围内的组件

您应该只有一个@Singleton范围的组件,如下所示:

@Singleton
@Component(modules={CommonModule.class, ExpModule.class})
public interface CommonComponent {

}

仅将“活动”,“片段”和“服务”指定为“组件”的显式注入目标

在Android应用中,您应该只将活动,片段和服务列为注入网站。您应该配置Dagger 2以注入其余的依赖项,而不必在其中调用component.inject(this)

例如,如果您的CommonClass看起来像这样:

public class CommonClass {
    @Inject Repository repository;

    public class CommonClass() {
         CommonComponentHolder.get().inject(this);
    }
}

像这样重写:

public class CommonClass {
    private final Repository repository;

    @Inject
    public class CommonClass(Repository repository) {
         this.repository = repository;
    }
}

现在,如果您有一个需要CommonClass的活动或片段,并且您正在注入CommonComponent或其子组件或相关组件之一,那么他们可以获取CommonClass有线的实例具有正确的依赖关系:

public class MyActivity extends AppCompatActivity {

    @Inject CommonClass commonClass;

    public void onCreate(Bundle savedInstanceState) {
        CommonComponentHolder.getComponent().inject(this);
    }
}

使用子组件或相关组件指定注入目标

现在你有一个@Singleton范围的组件,你可能想要为你的Activity或Fragment创建一个更窄范围的组件。您必须将其连接到CommonComponent,因此请使用相关组件或子组件(从Dagger 2.10开始,首选子组件)。既然你说你已经尝试定义@ExpScope,我认为缺少的部分是使用注入你的Activity或Fragment的@ExpScope制作子组件或依赖组件。

顶层单例组件的内容如下:

@Singleton
@Component(modules={CommonModule.class, ExpModule.class})
public interface CommonComponent {
    ExpComponent.Builder exComponent();
}

然后是子组件:

@ExpScope
@Subcomponent(modules = {NarrowerScopedModule.class})
public interface ExpComponent {
    @Subcomponent.Builder
    public interface Builder {
        Builder narrowerScopedModule(NarrowerScopedModule narrowerScopedModule);
        ExpComponent build();
    }
}

Google Android Architecture Blueprints Github repo

中有很好的Android项目工作示例