如何在Dagger 2

时间:2015-11-20 10:04:54

标签: 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

所以我制作了模块:

ApplicationModule:

@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

我做错了什么?感谢

1 个答案:

答案 0 :(得分:4)

简短的回答是......你做不到。

使用匕首,一切都在编译时完成。

  1. 您有一个应用程序组件,知道如何构建HelloPrinterParrot
    然后,为所有要使用的组件公开Parrot

  2. 您有自己的活动组件,也知道如何构建HelloPrinter

  3. 那会发生什么?

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

    applicationComponent.provideParrot().sayHello();
    

    这个很容易。你创建组件,你想要一个鹦鹉,它是使用已知的打印机构建的。

    activityComponent.provideParrot().sayHello();
    

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

    调用应用程序组件工厂并实例化parrot。由于应用程序模块知道如何构建打印机,因此它使用了手头的那个。

    ...现在是什么

    所以......你可以在你的活动组件中提供鹦鹉,然后他们会使用不同的打印机!

      

    Gradle:错误:Parrot多次绑定

    这里我们会得到2个鹦鹉进入我们的对象图,因为没有“覆盖”发生。这不起作用,也不应该。

    <强>结论

    无法覆盖方法。一旦声明第二个ParrotHelloPrinter,它将无法编译。

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

    如果我遗漏了某些内容,请纠正我,但我甚至没有办法使用命名注释保持签名相同。