如何让两个不同的@Providers在Dagger 2中注入相同的@Singleton?

时间:2017-11-21 20:29:21

标签: java dependency-injection dagger-2 dagger

考虑以下情况:

public class SessionManager implements HasSession, HasCredentials{
/**implementation here*/
}

我已经定义了一个SessionModule,只要请求注入HasSession或HasCredentials,就会注入SessionManager:

@Module
public abstract class SessionModule {
    @Provides @Singleton static HasSession hasSession(SessionManager sessionManager){
        return sessionManager;
    };

    @Provides @Singleton static HasCredentials hasCredentials(SessionManager sessionManager){
        return sessionManager;
    };
}

然后我定义了相应的组件:

@Component(modules={SessionModule.class})
@Singleton
public interface MyComponent {

    public HasSession getSessionProvider();

    public HasCredentials getCredentialsProvider();

}

getSessionProvider和getCredentialsProvider将创建/返回两个不同的SessionManager实例。

我希望在调用getSessionProvider或getCredentialsProvider时创建并返回一个单个的SessionManager实例。我怎样才能用Dagger 2来表达它?

2 个答案:

答案 0 :(得分:2)

你需要做两件事:

  1. 范围绑定,以便只有一个实例。
  2. 将范围绑定别名替换为备用类型。
  3. 首先,绑定范围:

    @Qualifier
    private @interface Scoped {}
    
    @Provides @Singleton
    @Scoped SessionManager scopeSessionManager(SessionManager manager) {
      return manager;
    }
    

    其次,别名为范围绑定:

    @Binds abstract HasSession bindHasSession(@Scoped SessionManager manager);
    @Binds abstract HasCredentials bindHasCredentials(@Scoped SessionManager manager);
    

    注意:这不会阻止此组件中的模块使用未范围的SessionManager,所以要小心。

    一种简单的解决方法,即使用@Component.Builder并使用@BindsInstance传递{em>有效范围的SessionManager的单个实例(从而无需上面的第一个代码片段,并允许您的原始代码工作)。

答案 1 :(得分:0)

我找到了解决这个问题的方法:只为SessionManager定义一个Singleton提供程序:

@Provides @Singleton
static SessionManager sessionManager(/*dependencies here*/){
    return new SessionManager(/**dependencies*/);
}