Dagger 2:将用户输入的参数注入对象 [英] Dagger 2: Injecting user inputted parameter into object

查看:111
本文介绍了Dagger 2:将用户输入的参数注入对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个类 Util ,它接受一个对象 - 类 Validator 的实例。

Say I have a class Util that takes in a object - an instance of class Validator.

由于我想避免在Util中实例化Validator类,我通过构造函数传递它:

Since I want to avoid instantiating the Validator class within Util, I pass it in via a constructor:

public class Utils {

   @Inject
   public Util(Validator validator) {

   }


}

我有一个提供Validator实例的模块:

I have a module that provides the Validator instance:

@Provides
@Singleton
PhoneNumberUtil provideValidator() {
    return Validator.getInstance();
}

以及Util类的实例:

and an instance of the Util class:

@Provides
Util provideUtil(Validator validator) {
    return new Utils(validator);
}

我有一个组件连线,它会给我一个Util的实例:

I have a component wired up that would give me an instance of Util:

Util getUtil()

所以在我的活动中,我可以这样称呼:

so within my activity, I could call it like:

Util myUtil = getComponent.getUtil();

所有这些都可以正常工作 - myUtil在实例化时有一个适当的Validator类实例。

All of that works fine - myUtil has a proper instance of Validator class when instantiated.

现在我想传入一个名为地址的字符串变量(通过UI输入用户)。我想更改构造函数,所以我传入Validator的实例和用户输入的字符串:

Now I want to pass in a String variable named address (which is user input via a UI). I want to change the constructor so I pass in both an instance of Validator and the user inputted String:

@Inject
public Util(Validator validator, String address) {

}

I只是无法理解如何传递第二个参数。有人能告诉我怎么样?

I just can't get my head around how to pass that 2nd parameter. Can someone tell me how?

理想情况下,我想实例化Util,如:

Ideally, I want to instantiate Util like:

Util myUtil = getComponent.getUtil(txtAddress.getText());


推荐答案

当我开始寻找时,我遇到了同样的问题几周前进入Dagger 2。我发现有关此信息(以及大多数其他与Dagger 2相关的问题)很难得到,所以我希望这会有所帮助!

I had the same question as you when I started looking into Dagger 2 a couple of weeks ago. I found information on this (and most other Dagger 2-related issues) difficult to come by, so I hope this helps!

最基本的答案是你做不到。您正在寻找的是被称为辅助注入的东西,它不是Dagger 2的一部分。其他一些依赖注入(DI)框架,例如 Guice ,确实提供此功能,因此您可以查看这些功能。当然,仍然有办法使用Dagger 2做你想做的事。

The most basic answer is that you cannot. What you are looking for is something that is called assisted injection, and it is not part of Dagger 2. Some other dependency injection (DI) frameworks, such as Guice, do offer this feature, so you might look into those. Of course, there are still ways to do what you want to do using Dagger 2.

与DI结合使用的标准方法是使用Factory模式。基本上,您创建一个可注入的工厂类,它将运行时参数(例如 address )作为它提供的对象创建方法的参数。

The standard way to do what you want to do in combination with DI is by using the Factory pattern. Basically, you create an injectable factory class that takes runtime parameters such as address as arguments to the object creation methods that it provides.

在你的情况下,你需要一个 UtilFactory ,Dagger 2在瞬间注入一个 Validator 提供了一个方法 create(String address),它创建了 Util 的实例。 UtilFactory 应保留对 Validator 的注入实例的引用,以便它具有创建<的实例所需的一切code> Util 在 create 方法中。

In your case, you would need a UtilFactory into which Dagger 2 injects a Validator upon instantation and which offers a method create(String address) that creates instances of Util. UtilFactory should keep a reference to the injected instance of Validator so that it has everything it needs to create an instance of Util in the create method.

许多代码的代码这样的工厂可能很麻烦。你一定要看看 AutoFactory ,这可以减轻一些负担。 Guice的辅助注射似乎与Dagger 2 + AutoFactory非常相似(虽然具有更好的语法糖)。

Wring code for many such factories can be cumbersome. You should definitely take a look at AutoFactory, which eases some of the burden. Guice's assisted injection seems to work quite similar to Dagger 2 + AutoFactory (albeit with even nicer syntactic sugar).

我怀疑这是你想在这种情况下做的事情,但你可以只创建一个提供地址的模块(并实例化一个新组件)。您不必为每个可能的地址创建新的@Module类。相反,您可以将地址作为参数传递给模块的构造函数。您可以使用teano建议的@BindsInstance-annotation来获得类似的结果。

I doubt this is something that you would like to do in this case, but you could just create a module that provides the address (and instantiate a new component). You do not have to create a new @Module class for every possible address. Instead, you can just pass the address as an argument to the constructor of the module. You could use the @BindsInstance-annotation as suggested by teano to achieve a similar result.

我不确定这是否是反模式。对我来说,在某些情况下,这似乎是一种可接受的路线,但只有在您实际使用相同的路线时,例如初始化许多对象的地址。您绝对不希望为每个需要注入的对象实例化一个新组件一个新模型。效率不高,如果你不小心,你会得到比没有Dagger更多的样板代码。

I am not sure if this is an anti-pattern or not. To me, this seems like an acceptable route in some cases, but only when you are actually using the same e.g. address for the initialisation of "many" objects. You definitely do not want to instantiate a new component and a new model for each object that requires injection. It is not efficient, and if you are not careful you will end up with more boilerplate code than without Dagger.

在了解DI框架时,对我来说非常有用的东西是使用DI框架确实意味着你必须要DI到初始化所有对象。根据经验:在编译时注入你知道的并且与其他对象有静态关系的对象;不要注入运行时信息。

Something that was immensely useful to me when learning about DI frameworks was the realisation that using a DI framework does not mean that you have to DI to initialise all of your objects. As a rule of thumb: inject objects that you know of at compile time and that have static relations to other objects; do not inject runtime information.

我认为这个是关于这个主题的好帖子。它介绍了'newables'和'injectables'的概念。

I think this is a good post on the subject. It introduces the concept of 'newables' and 'injectables'.


  • Injectables 是靠近根的类你的DI图。这些类的实例是您希望DI框架提供和注入的对象类型。管理者或服务类型对象是注射剂的典型示例。

  • Newables 是DI图边缘的对象,或者甚至不是实际的一部分你的DI图表。 整数地址等是新手的例子。

  • Injectables are the classes near the root of your DI graph. Instances of these classes are the kind of objects that you expect your DI framework to provide and inject. Manager- or service-type objects are typical examples of injectables.
  • Newables are objects at the fringes of your DI graph, or that are not even really part of your DI graph at all. Integer, Address etc. are examples of newables.

从广义上讲,newables是被动对象,注入或嘲弄它们是没有意义的。它们通常包含应用程序中的数据,并且仅在运行时可用(例如,您的地址)。 Newables不应该保留对注射剂的引用,反之亦然(该帖子的作者称之为可注射/可新生 - 分离)。

Broadly speaking, newables are passive objects, and there is no point in injecting or mocking them. They typically contain the "data" that is in your application and that is only available at runtime (e.g. your address). Newables should not keep references to injectables or vice versa (something the author of the post refers to as "injectable/newable-separation").

实际上,我发现在注射剂和新药之间做出明确区分并不总是容易或可能的。尽管如此,我认为它们是很好的概念,可以用作思考过程的一部分。在将另一个工厂添加到您的项目之前一定要三思而后行!

In reality, I have found that it is not always easy or possible to make a clear distinction between injectables and newables. Still, I think that they are nice concepts to use as part of your thinking process. Definitely think twice before adding yet another factory to your project!

在您的情况下,我认为处理 Util 作为注射剂,地址为新的。这意味着该地址不应该是 Util 类的一部分。如果您想使用 Util 的实例,例如验证/ ...地址,只需将您要验证的地址作为验证/ ...方法的参数传递。

In your case, I think it would make sense to treat Util as an injectable and the address as a newable. This means that the address should not be part of the Util class. If you want to use instance of Util for e.g. validating/... addresses, just pass the address that you want to validate as an argument to the validation/... method.

这篇关于Dagger 2:将用户输入的参数注入对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆