这是在 Dagger 2 中向构造函数添加参数的正确方法吗?

Is this the correct way of adding parammeters to constructor in Dagger 2?

上下文

最近我开始研究依赖注入和 Dagger 2。它看起来是一个不错的库,但对我来说似乎有点混乱。在某些情况下,我不知道该如何继续。

我尝试了什么

我创建了一个简单的 Android 应用程序,它创建了一个客户端及其依赖项并执行一些(虚拟)工作。这些是 类:

Client.java

public class Client {

    private Dependency dep;

    @Inject
    public Client(Dependency dep) {
        this.dep = dep;
    }

    public void work() {
        System.out.println("Client working");
        dep.doWork();
    }
}

Dependency.java

public class Dependency {

    @Inject
    public Dependency() {
    }

    public void doWork() {
        System.out.println("Dependency working");
    }
}

根据一些教程,我创建了几个模块 类:

DependencyModule.java

@Module
public class DependencyModule {

    @Provides
    Dependency provideDependency() {
        return new Dependency();
    }
}

ClientModule.java

@Module
public class ClientModule {

    @Provides
    Client provideClient(Dependency dep) {
        return new Client(dep);
    }

}

还有组件接口:

@Component(modules = {ClientModule.class})
public interface ClientComponent {

    Client provideClient();

}

这很好用。从我的 activity 我可以执行以下操作并且有效:

ClientComponent clientComp = DaggerClientComponent
                .builder()
                .clientModule(new ClientModule())
                .build();

Client client = clientComp.provideClient();
client.work();

问题

我了解如何在客户端中注入依赖项(至少我是这么认为的)。但是我如何将参数添加到 client/dependency?

的构造函数中

我的意思是,如果我想向我的对象添加一些 int 参数怎么办?就这么简单:

Client.java

public class Client {

    int id;
    Dependency dep;

    @Inject
    public Client(int id, Dependency dep) {
        this.id = id;
        this.dep = dep;
    }

    public void work() {
        System.out.println("id: " + id + " Client working");
        dep.doWork();
    }
}

Dependency.java

public class Dependency {

    private int id;

    @Inject
    public Dependency(int id) {
        this.id = id;
    }

    public void doWork() {
        System.out.println("id: " + id + " Dependency working");
    }
}

注意: 下面的代码是我试过的。所以我不确定它的正确性。

因此,由于对象在其构造函数中具有新参数,因此模块必须更改:

DependencyModule.class

public class DependencyModule {

    @Provides
    Dependency provideDependency() {
        return new Dependency(id);
    }
}

ClientModule.class

@Module
public class ClientModule {

    @Provides
    Client provideClient(int id, Dependency dep) {
        return new Client(id, dep);
    }

}

问题

如何使用新模块?我还没有找到将 id 传递给该方法的方法。我让它工作的唯一方法是将它传递给 Module 构造函数并将其从 provide 方法中删除。这样:

@Module
public class ClientModule {

    private int id;

    public ClientModule(int id) {
        this.id = id;
    }

    @Provides
    Client provideClient(Dependency dep) {
        return new Client(id, dep);
    }

}

DependencyModule.java 中的方法相同。

这样,在 ClientComponent 接口中添加 DependencyModule.class 我可以做类似的事情:

ClientComponent clientComp = DaggerClientComponent
                .builder()
                .clientModule(new ClientModule(clientId))
                .dependencyModule(new DependencyModule(dependencyId))
                .build();

Client client = clientComp.provideClient();
client.work();

这是正确的做法吗?

有没有更好的方法达到同样的效果?

我是否违反了 DI 原则?

有两种基本方法可以让 Dagger 提供一个 class:

的实例
  1. @Inject 添加到构造函数,并将 class 的依赖项作为构造函数参数放入。

  2. @Provides 注释的方法添加到 @Module 注释的 class,并将该模块安装到您的 @Component.

每个 class 您只需要使用一种方法。因此,在您的第一个示例中, ClientDependency 可以正常使用;你不需要 ClientModuleDependencyModule.

添加 int 依赖项后,现在您确实需要一个模块,因为没有 class 到 @Inject。该模块只需要提供 int,这样就可以了:

@Module
public class ClientIdModule {
  private final clientId;

  public ClientIdModule(int clientId) {
    this.clientId = clientId;
  }

  @Provides
  static int clientId() {
    return clientId;
  }
}

现在,如果您将 ClientIdModule 安装到您的组件中,您将能够获得具有正确 ID 的 Client,它的 Dependency 也将如此。