java - 如何覆盖 Dagger 2 范围内的依赖项

标签 java android dependency-injection dagger dagger-2

如何覆盖 Dagger 2 不同范围内的依赖项?示例:

我的应用程序中有两个组件:ApplicationComponentActivityComponentApplicationComponent 是基础组件,ActivityComponent 是我要执行覆盖的作用域组件。

对于这个例子,我创建了那些模型:

public class Parrot {

    private final HelloPrinter helloPrinter;

    public Parrot(HelloPrinter helloPrinter) {
        this.helloPrinter = helloPrinter;
    }

    public void sayHello(){
        helloPrinter.print();
    }
}


public interface HelloPrinter {
    void print();
}


public class AppHelloPrinter implements HelloPrinter{

    @Override
    public void print() {
        System.out.println("Hello Application");
    }
}

public class ActivityHelloPrinter implements HelloPrinter {
    @Override
    public void print() {
        System.out.println("Hello Activity");
    }
}

还有代码:

ApplicationComponent applicationComponent = DaggerApplicationComponent.builder().build();
applicationComponent.provideParrot().sayHello();
activityComponent = DaggerActivityComponent.builder()
                        .applicationComponent(applicationComponent).build();
activityComponent.provideParrot().sayHello();

我想要的输出是:

Hello Application
Hello Activity

所以我制作了模块:

应用模块:

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

    Parrot provideParrot();
}

@Module
public class ApplicationModule {

    @Provides
    @Singleton
    HelloPrinter providePrinter(){
        return new AppHelloPrinter();
    }

    @Provides
    Parrot provideParrot(HelloPrinter helloPrinter) {
        return new Parrot(helloPrinter);
    }

}

ActivityModule:尝试覆盖 HelloPrinter

@PerActivity
@Component(dependencies = ApplicationComponent.class, modules = ActivityModule.class)
public interface ActivityComponent {

    Parrot provideParrot();

}

@Module
@PerActivity
public class ActivityModule {

    @Provides
    @PerActivity
    HelloPrinter provideHelloPrinter() {
        return new ActivityHelloPrinter();
    }     
}

但是使用这个配置输出是:

Hello Application
Hello Application

我做错了什么?谢谢

最佳答案

简短的回答是......你不能那样做。

对于 dagger,一切都在编译时完成。

  1. 您有一个应用程序组件,它知道如何构造一个HelloPrinter 和一个Parrot
    然后,您公开 Parrot 以供所有组件使用。

  2. 你有你的 Activity 组件,它也知道如何构造一个 HelloPrinter!

那么会发生什么?

请记住对象图。组件知道它们可以构建什么并依赖于其他组件,从而公开已知对象。

applicationComponent.provideParrot().sayHello();

这个很简单。您创建了组件,您想要一只鹦鹉,它是使用已知打印机构建的。

activityComponent.provideParrot().sayHello();

这里发生的事情(基本上)是一样的。你说你想要一只鹦鹉。您的 Activity 组件不知道如何制作打印机,它只知道如何制作打印机!
但是等等。它依赖于一个应用程序组件,方便地公开一个 Parrot 工厂。

应用程序组件工厂被调用并且鹦鹉被实例化。由于应用程序模块知道如何构建打印机,因此它会使用手边的打印机。

...现在怎么办

所以...您可以在您的 Activity 组件中提供 Parrots,然后它们将使用不同的打印机!

Gradle: error: Parrot is bound multiple times

这里我们将 2 只鹦鹉放入我们的对象图中,因为没有发生“覆盖”。这行不通,也不应该。

结论

无法覆盖 方法。一旦声明了第二个 ParrotHelloPrinter,它就会编译失败。

实现类似功能的唯一可能性是在要使用的打印机上使用 @Named() 注释和/或将整个鹦鹉创建拉到 Activity 模块中。

如果我遗漏了什么请纠正我,但我什至没有看到使用命名注释保持签名相同的方法。

关于java - 如何覆盖 Dagger 2 范围内的依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33823916/

相关文章:

java - 如何在阻塞代码的情况下连续读取 Java 套接字的输入流?

java - Spring4配置CommonsMultipartResolver失败

c# - Ninject 按约定绑定(bind)不适用于泛型类型

java - Servlet 3.0 的构造函数依赖注入(inject)?

java - Trove jar THashMap 类未找到异常

更改类文件后 Android 上出现 java.lang.NoClassDefFoundError

android - Firebase 多播云消息传递

grails - 依赖注入(inject)在 Grails 服务中不起作用

android - 无法从Android中的 Assets 文件夹复制sqlite数据库

android - 无法 ACTION_VIEW 外部存储上的文件