Dagger注入错误的类(注入父类而不是子类)

时间:2016-06-13 07:06:13

标签: android dependency-injection dagger-2

我正在开发几个连接到相同API的应用程序,所以我决定创建公共类,将它们放在一个模块中并在所有项目中共享它们。

例如,我的共享模块中有以下类

// This is a bass class, no application will use it.
public class GetPlayerInteractor extends ApiInteractor {

  @Inject
  public GetPlayerInteractor(ThreadExecutor threadExecutor,
                             PostExecutionThread postExecutionThread,
                             RestClient restClient,
                             RequestTokenInteractor requestTokenInteractor) {
    super(threadExecutor, postExecutionThread, restClient, requestTokenInteractor);
  }
}

// This class will accept GetPlayerInteractor or its children class as argument.
public class PlayerAuthenticationInteractor extends ApiInteractor {

  @Inject
  public PlayerAuthenticationInteractor(ThreadExecutor threadExecutor,
                                        PostExecutionThread postExecutionThread,
                                        RestClient restClient,
                                        RequestTokenInteractor requestTokenInteractor,
                                        GetPlayerInteractor getPlayerInteractor) {
    super(threadExecutor, postExecutionThread, restClient, requestTokenInteractor,
        getPlayerInteractor);
  }
}

并在包含模块的应用程序中

// This one is the actual class I need to inject
public class GetPlayerByEmailInteractor extends GetPlayerInteractor {

  private GetDomainNameInteractor getDomainNameInteractor;

  @Inject
  public GetPlayerByEmailInteractor(ThreadExecutor threadExecutor,
                                    PostExecutionThread postExecutionThread,
                                    RestClient restClient,
                                    RequestTokenInteractor requestTokenInteractor,
                                    GetDomainNameInteractor getDomainNameInteractor) {
    super(threadExecutor, postExecutionThread, restClient, requestTokenInteractor, getPlayerCustomFieldsInteractor);

    this.getDomainNameInteractor = getDomainNameInteractor;
  }
}

这是应用程序中的UserModule

@Module
public class UserModule {

  @Provides
  @PerActivity
  GetPlayerInteractor provideGetPlayerInteractor(ThreadExecutor threadExecutor,
                                                 PostExecutionThread postExecutionThread,
                                                 RestClient restClient,
                                                 RequestTokenInteractor requestTokenInteractor,
                                                 GetDomainNameInteractor getDomainNameInteractor) {
    Log.i("Dev", "Create GetPlayerInteractor");
    return new GetPlayerByEmailInteractor(threadExecutor, postExecutionThread, restClient, requestTokenInteractor, getDomainNameInteractor);
  }

  @Provides
  @PerActivity
  PlayerAuthenticationInteractor providePlayerAuthenticationInteractor(ThreadExecutor threadExecutor,
                                                                       PostExecutionThread postExecutionThread,
                                                                       RestClient restClient,
                                                                       RequestTokenInteractor requestTokenInteractor,
                                                                       GetPlayerByEmailInteractor getPlayerByEmailInteractor) {
    Log.i("Dev", "Create PlayerAuthenticationInteractor");
    return new PlayerAuthenticationInteractor(threadExecutor, postExecutionThread, restClient, requestTokenInteractor, getPlayerByEmailInteractor);
  }
}

我从来没有为GetPlayerInteractor编写@Provide,因为它只是一个基类,但由于某些原因,GetPlayerByEmailInteractor从未创建,登录两个提供方法永远不会打印(也是我设置永远不会切换的断点)并且我将getPlayerInteractor作为参数PlayerAuthen而不是getPlayerByEmailInteractor。

另外,如果我同时删除

@Provide
@PerActivity
GetPlayerInteractor provideGetPlayerInteractor(...)

@Provide
@PerActivity
PlayerAuthenticationInteractor providePlayerAuthenticationInteractor(...)

构建仍然成功,应用程序可以运行

当我查看DaggerApplicationComponent时,我看到如下

public final class DaggerApplicationComponent implements ApplicationComponent {
  // Some other classes
  private Provider<GetPlayerInteractor> getPlayerInteractorProvider;
  private Provider<PlayerAuthenticationInteractor> playerAuthenticationInteractorProvider;
  // Some other classes
  private Provider<GetPlayerByEmailInteractor> getPlayerByEmailInteractorProvider;
  // Some other classes

  private void initialize(final Builder builder) {
  // Some other classes
  this.getPlayerInteractorProvider = ...
  this.playerAuthenticationInteractorProvider = PlayerAuthenticationInteractor_Factory.create((MembersInjector) MembersInjectors.noOp(), provideThreadExecutorProvider, providePostExecutionThreadProvider, provideRestClientProvider, provideRequestTokenInteractorProvider, getPlayerInteractorProvider);
  // Some other classes
  this.getPlayerByEmailInteractorProvider = ...

    }
}

请注意,传递给PlayerAuthenticationInteractor_Factory的lass参数是 getPlayerInteractorProvider 而不是 getPlayerByEmailInteractorProvider

我错了。

1 个答案:

答案 0 :(得分:1)

UserPresenter provideUserPresenter(GetUserUseCase getUserUseCase)

告诉匕首你想要GetUserUseCase

@Inject
public GetEmployeeUseCase()

@Inject
public GetEmployeeUseCase()

你的GetUserUseCase和它的孩子都可以通过构造函数注入提供,但是因为你请求GetUserUseCase这就是你得到的。

如果您不想使用GetUserUseCase请勿申请。简单的方法是修复您的提供方法:

UserPresenter provideUserPresenter(GetEmployeeUseCase getUserUseCase)

哪种情况好,因为您提供的 的逻辑仍然在模块中,而不在您的业务逻辑中。如果你想要/必须提供你的超类,请从中删除@Provides并创建一个像下面这样的提供方法来告诉dagger你想要使用的子类:

@Provides GetUserUseCase provideUserUseCase(GetEmployeeUseCase getUserUseCase) {
    return getUserUseCase;
}

这只会将您的子类实现映射到父类。如果您不删除父项上的@Inject注释,则会导致一些多个提供方法... 错误。