2015-11-20 67 views
4

如何覆盖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 

什么我做错了吗?谢谢

+0

我认为在Dagger2中不可能覆盖模块。如果它适合你,你可以尝试将它们标记为@Named(“Activity”)和@Named(“Application”) –

回答

2

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

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

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

  2. 你有你的活动组件,也知道如何构建一个HelloPrinter

那么会发生什么?

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

applicationComponent.provideParrot().sayHello(); 

这个很简单。你创建组件,你需要一个鹦鹉,它是使用已知的打印机构造的。

activityComponent.provideParrot().sayHello(); 

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

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

......现在是什么

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

Gradle: error: Parrot is bound multiple times

这里我们会得到2个鹦鹉到我们的对象图中,因为没有“覆盖”发生。这是行不通的,不应该。

结论

没有办法覆盖方法。只要您声明第二个ParrotHelloPrinter它将无法编译。

实现类似功能的唯一可能性是使用@Named()注释,以便打印机使用和/或将整个鹦鹉创建向下拖入活动模块。

请纠正我,如果我失去了一些东西,但我甚至没有看到使用命名注释保持签名的方式。