User's Guide Of Dagger2

dagger2 官方文档。  因为最近看了一下dagger2 感觉非常不错。

原文地址:  


csdn 文章排版比较乱,也可以参看这里。
http://note.youdao.com/noteshare?id=c16171f524e5a1efc8a3ddee0d2ea6f6&sub=7B5CAD89E9994A88BB96B5284B02F300


以下是原文:

The best classes in any application are the ones that do stuff: the  BarcodeDecoder , the  KoopaPhysicsEngine , and the  AudioStreamer . These classes have dependencies; perhaps a  BarcodeCameraFinder DefaultPhysicsEngine , and an  HttpStreamer .

在application中,最好的类是那些只做任务的类。 比如 BarcodeDecoder,KoopaPhysicsEngine,AudioStreamer 这些类通常会有依赖的类,比如BarcodeCameraFinder,DefaultPhysicsEngine,HttpStreamer


To contrast, the worst classes in any application are the ones that take up space without doing much at all: the  BarcodeDecoderFactory , the  CameraServiceLoader , and the  MutableContextWrapper . These classes are the clumsy duct tape that wires the interesting stuff together.

与之相对的,最糟糕的类,是那些占了位置,不好好做事情的类。
BarcodeDecoderFactory,CameraServiceLoader,MutableContextWrapper
这些类只是起一个粘合剂的作用,它们把感兴趣的类集合在了一起。

Dagger is a replacement for these  FactoryFactory  classes that implements the  dependency injection  design pattern without the burden of writing the boilerplate. It allows you to focus on the interesting classes. Declare dependencies, specify how to satisfy them, and ship your app.


Dagger 就是这样一种替代方法,去替换类似FactoryFactory 这种实现依赖的类。它基于注入设计思想,不需要你写繁琐的些公式化的代码,这似的你可以集中精力去做有意义的事情。
只需要声明依赖,就可以很爽的去使用它们。(这句话是我自己的理解)


By building on standard  javax.inject  annotations ( JSR 330 ), each class is  easy to test . You don’t need a bunch of boilerplate just to swap the  RpcCreditCardService  out for a  FakeCreditCardService .

通过使用标准的java,inject 注解。 任何类都可以很容易的去使用。你不需要再写一大堆无用的代码,仅仅是为了把FakeCreditCardService 中的RpcCreditCardService 更换。


Dependency injection isn’t just for testing. It also makes it easy to create  reusable, interchangeable modules . You can share the same  AuthenticationModule  across all of your apps. And you can run  DevLoggingModule  during development and  ProdLoggingModule  in production to get the right behavior in each situation.

依赖注入,不仅仅有利于测试,而且还具有可复用,可替换,模块化的优点。比如,你可以在你的app中共享
类似AuthenticationModule 的模块。你可以通过DevLoggingModule ,ProdLoggingModule 来区分开发环境和生成环境。等等。


Why Dagger 2 is Different
Dependency injection  frameworks have existed for years with a whole variety of APIs for configuring and injecting. So, why reinvent the wheel? Dagger 2 is the first to  implement the full stack with generated code . The guiding principle is to generate code that mimics the code that a user might have hand-written to ensure that dependency injection is as simple, traceable and performant as it can be. For more background on the design, watch  this talk  ( slides ) by  +Gregory Kick .

依赖注入框架已经存在了很多年。并且有一大把的api可以配置和注入。那我们为什么要重复造轮子呢。
Dagger2 是第一个实现全栈生成代码的框架,我们的原则是生成用户可能需要手写的代码,来保证依赖注入是简单的,可追踪,可操作的。 更多的设计理念,可以看这个人的google+


Using Dagger
We’ll demonstrate dependency injection and Dagger by building a coffee maker. For complete sample code that you can compile and run, see Dagger’s  coffee example .

我们将会演示 Dagger实现依赖注入,通过一个咖啡壶的例子。 完整的例子请看这里。


Declaring Dependencies
Dagger constructs instances of your application classes and satisfies their dependencies. It uses the  javax.inject.Inject annotation to identify which constructors and fields it is interested in.
Use  @Inject  to annotate the constructor that Dagger should use to create instances of a class. When a new instance is requested, Dagger will obtain the required parameters values and invoke this constructor.
class Thermosiphon implements Pump { private final Heater heater ; @Inject Thermosiphon ( Heater heater ) { this. heater = heater ; } ... }



声明依赖
Dagger构造器实例实现你的app依赖,通过使用javax.inject注解来表明,哪个构造器和字段是它所需要的。
通过使用@Inject注解构造器,Dagger会使用它去实例化这个类。当一个新的实例被需要的时候,Dagger将会按照需要的参数来调用构造器方法


Dagger can inject fields directly. In this example it obtains a  Heater  instance for the  heater  field and a  Pump  instance for the  pump field.
class CoffeeMaker { @Inject Heater heater ; @Inject Pump pump ; ... }


Dagger可以成功注入字段,在这个例子中,他将会完成一个Heater实例给heater 字段,并且完成一个Pump实例给 pump字段

If your class has  @Inject -annotated fields but no  @Inject -annotated constructor, Dagger will inject those fields if requested, but will not create new instances. Add a no-argument constructor with the  @Inject  annotation to indicate that Dagger may create instances as well.
Dagger also supports method injection, though constructor or field injection are typically preferred.
Classes that lack  @Inject  annotations cannot be constructed by Dagger.

如果你的类,只有加了@Inject的字段,而没有加了@Inject的构造器,Dagger依然会在需要的时候注入这些字段。但是不会创建实例。
给这种类的无参构造器添加一个@Inject 可以让dagger工作的更好。
dagger统一支持方法注解,虽然构造器和字段注解是更好的方法。
没有加注解的方法,dagger无法创建。


Satisfying Dependencies
By default, Dagger satisfies each dependency by constructing an instance of the requested type as described above. When you request a  CoffeeMaker , it’ll obtain one by calling  new CoffeeMaker()  and setting its injectable fields.
But  @Inject  doesn’t work everywhere:
  • Interfaces can’t be constructed.
  • Third-party classes can’t be annotated.
  • Configurable objects must be configured!
For these cases where  @Inject  is insufficient or awkward, use an  @Provides -annotated method to satisfy a dependency. The method’s return type defines which dependency it satisfies.
For example,  provideHeater()  is invoked whenever a  Heater  is required:

一般情况下,dagger通过构造一个对象来实现被要求的实例,当你需要一个CoffeeMaker的时候,只需要调用CoffeeMaker()就可以了。
但是dagger 不是无所不能的
接口不能被构造
第三方包不能被注解
配置对象必须存在
针对以上三点是dagger的不足之处。需要使用@provides注解在需要提供视力的地方。
比如,provideHeater() 会在Heater被需要的时候调用。

@Provides static Heater provideHeater () { return new ElectricHeater (); }
It’s possible for  @Provides  methods to have dependencies of their own. This one returns a  Thermosiphon  whenever a  Pump  is required:

也有可能,@Provides 依赖于自身,下面这个例子中所以的Pump 请求都会返回同一个实例。

@Provides static Pump providePump ( Thermosiphon pump ) { return pump ; }
All @Provides methods must belong to a module. These are just classes that have an  @Module annotation.
所有的@Provides 方法必须属于一个module.只有class才能用到@module注解

@Module class DripCoffeeModule { @Provides static Heater provideHeater () { return new ElectricHeater (); } @Provides static Pump providePump ( Thermosiphon pump ) { return pump ; } }
By convention,  @Provides  methods are named with a  provide  prefix and module classes are named with a  Module  suffix.

按照约定,所有的@Provides方法应该以 provide为前缀,所有的module class都应该以Module为前缀


Building the Graph
The  @Inject  and  @Provides -annotated classes form a graph of objects, linked by their dependencies. Calling code like an application’s  main  method or an Android  Application  accesses that graph via a well-defined set of roots. In Dagger 2, that set is defined by an interface with methods that have no arguments and return the desired type. By applying the  @Component annotation to such an interface and passing the  module  types to the  modules  parameter, Dagger 2 then fully generates an implementation of that contract.

@Inject和@Provides 注解通过链接他们各自的依赖,构成他们的对象图谱。在Java的Main方法或者android的Application中可以把这些对象归类到一个根集合。
在dagger2中,这个集合以interface的的方法体现。 它们没有参数,并且返回其需要的类型。通过使用  @Component标签在这样的Interface中来传递module的类型和参数。dagger2会根据约束来全自动生成其实现。

@Component ( modules = DripCoffeeModule . class ) interface CoffeeShop { CoffeeMaker maker (); }
The implementation has the same name as the interface prefixed with  Dagger . Obtain an instance by invoking the  builder() method on that implementation and use the returned  builder  to set dependencies and  build()  a new instance.

这些实现会用Dagger来做前缀,获取一个实例的方法就是去调用Builder实现类的builder()方法。然后它会实现其依赖,并且返回一个新的实例。

CoffeeShop coffeeShop = DaggerCoffeeShop . builder () . dripCoffeeModule (new DripCoffeeModule ()) . build ();
Note : If your  @Component  is not a top-level type, the generated component’s name will be include its enclosing types’ names, joined with an underscore. For example, this code:

如果你的@Component标签,不是一个最高级的类型,那么最后胜出的低吗有可能会包含其上级类型的名字,并连接下划线。就像下面。

class Foo { static class Bar { @Component interface BazComponent {} } }


would generate a component named  DaggerFoo_Bar_BazComponent .
会生成一个叫 DaggerFoo_Bar_BazComponent 的组件

Any module with an accessible default constructor can be elided as the builder will construct an instance automatically if none is set. And for any module whose  @Provides  methods are all static, the implementation doesn’t need an instance at all. If all dependencies can be constructed without the user creating a dependency instance, then the generated implementation will also have a  create()  method that can be used to get a new instance without having to deal with the builder.

所有包含默认构造器的module都会被自动省略为一个budiler,通过自动构造方法。
如果一个module所有的@provides的方法都是静态的,那么他的实现也不需要生成实例。
如果一个module的所有的依赖都可以不需要用户配置,而自己实现构造,那么它的生成的代码会自动拥有一个无参数的create方法, 这个方法可以让用户不需要任何操作而获取一个其实例。

Now, our  CoffeeApp  can simply use the Dagger-generated implementation of  CoffeeShop  to get a fully-injected  CoffeeMaker .

现在,我们的CoffeeApp 就简单的使用了dagger自动生成的代码获取了一个CofferMaker的完全注入对象。

public class CoffeeApp { public static void main ( String [] args ) { CoffeeShop coffeeShop = DaggerCoffeeShop . create (); coffeeShop . maker (). brew (); } }
Now that the graph is constructed and the entry point is injected, we run our coffee maker app. Fun.
现在,当我们允许我们的app的时候,会看到注入的点和构造器图谱。

$ java -cp ... coffee.CoffeeApp~ ~ ~ heating ~ ~ ~=> => pumping => => [_]P coffee! [_]P


Bindings in the graph
The example above shows how to construct a component with some of the more typical bindings, but there are a variety of mechanisms for contributing bindings to the graph. The following are available as dependencies and may be used to generate a well-formed component:

上面的例子,告诉了我们如果通过一些典型的绑定来构造一个Component.但是这里还有一些特殊情况下的绑定。下面是可以使用的依赖,或许可以用来生成更好的代码实现。

  • Those declared by @Provides methods within a @Module referenced directly by @Component.modules or transitively via @Module.includes

在module里面声明的所有@provides方法都会被 Component.modules直接引用。或者被module里面的Includes间接引用。

  • Any type with an @Inject constructor that is unscoped or has a @Scope annotation that matches one of the component’s scopes

包含@Inject的构造器都没有scope标签,或者默认拥有一个component声明周期的scope注解。


  component dependencies   component provision methods (这个两个专属名词,我没看明白)

  • The component itself

component自身

不合格的builders 对于所有使用它的子component

  • Provider or Lazy wrappers for any of the above bindings
provider或者lazy 包装, 对其上述的所有绑定

  • Provider of a Lazy of any of the above bindings (e.g., Provider<Lazy<CoffeeMaker>>)

provider并且lazy 包装, 对其上述的所有绑定 (e.g.,  Provider<Lazy<CoffeeMaker>> )
  • MembersInjector for any type

任意类型的MembersInjector  注解对象


Singletons and Scoped Bindings

Annotate an  @Provides  method or injectable class with  @Singleton . The graph will use a single instance of the value for all of its clients.

所有@provides的方法或者可注解的class 如果被@singleton修饰,那么依赖图会让所有的客户端都只拥有一个单例。

@Provides @Singleton static Heater provideHeater () { return new ElectricHeater (); }
The  @Singleton  annotation on an injectable class also serves as  documentation . It reminds potential maintainers that this class may be shared by multiple threads.

@Singleton标签也想documentation注解一下。 他有可能会被多个线程公用一个对象。

@Singleton class CoffeeMaker { ... }
Since Dagger 2 associates scoped instances in the graph with instances of component implementations, the components themselves need to declare which scope they intend to represent. For example, it wouldn’t make any sense to have a @Singleton  binding and a  @RequestScoped  binding in the same component because those scopes have different lifecycles and thus must live in components with different lifecycles. To declare that a component is associated with a given scope, simply apply the scope annotation to the component interface.

因为daager2的相关范围实例 与组件的实例实现相关。 所有这些components本身需要声明他们所存在的周期。
比如,在一个component类中同事存在一个@singleton 和@RequestScoped的绑定,那么他们不会有任何作用,因为他们的声明周期完全不同。而且因为他们必须在同一个component内依赖不同的周期。
component的声明周期是由scope赋予的

@Component ( modules = DripCoffeeModule . class ) @Singleton interface CoffeeShop { CoffeeMaker maker (); }
Components may have multiple scope annotations applied. This declares that they are all aliases to the same scope, and so that component may include scoped bindings with any of the scopes it declares.


Component可以拥有多个scope的注解修饰。所有的别名都拥有统一的scpe.这样的component就可以在他声明的周期之内,拥有任意周期的声明。

Reusable scope
Sometimes you want to limit the number of times an  @Inject -constructed class is instantiated or a  @Provides  method is called, but you don’t need to guarantee that the exact same instance is used during the lifetime of any particular component or subcomponent. This can be useful in environments such as Android, where allocations can be expensive.

有些时候,你想限制注入构造器的次数或者某个 @providers方法的调用次数。但是你不需要保证特殊的component和子component也必须使用完全一样的实例。
这个方向在类似android的内存紧张的环境下会很有用。


For these bindings, you can apply  @Reusable  scope.  @Reusable -scoped bindings, unlike other scopes, are not associated with any single component; instead, each component that actually uses the binding will cache the returned or instantiated object.

对于这些绑定,你可以使用@Resuable 标签。与其他的scope不同,他不是某个component所特有的,而是每个使用这个绑定的component都会缓存实例化或者返回得到的对象。

That means that if you install a module with a  @Reusable  binding in a component, but only a subcomponent actually uses the binding, then only that subcomponent will cache the binding’s object. If two subcomponents that do not share an ancestor each use the binding, each of them will cache its own object. If a component’s ancestor has already cached the object, the subcomponent will reuse it.

这意味着,如果安装了某个@resable修饰的module. 那么如果有一个子commponent实际使用了这个绑定,那么只有这个子component会有魂村这个绑定对象,如果有两个子components并他们没有通过一个共同的父类共享这个组件,那么他们会各自缓存一个对象。 如果他们的父类已经缓存了,那么他们会共享它。

There is no guarantee that the component will call the binding only once , so applying  @Reusable  to bindings that return mutable objects, or objects where it’s important to refer to the same instance, is dangerous. It’s safe to use  @Reusable  for immutable objects that you would leave unscoped if you didn’t care how many times they were allocated.


因为这个标签不能保证component只绑定一次。所以如果用@reusable来绑定可修改的对象,或者对象引用的同一个实例的时候是很危险的。 当用它来修饰那些你没有标记其周期,不在乎它被申请多少次内存的不可更改的对象时,才是安全的。

Releasable references
When a binding uses a scope annotation, that means that the component object holds a reference to the bound object until the component object itself is garbage-collected. In memory-sensitive environments such as Android, you may want to let scoped objects that are not currently being used be deleted during garbage collection when the application is under memory pressure.
In that case, you can define a scope and annotate it with  @CanReleaseReferences .

当你绑定一个 scope类型的注解时,那就意味着,这个component的对象将会持有整个component的对象引用。知道这个component对象自己被gc掉。 在内存敏感的环境下,比如android。 你需要使用scoped的对象在不使用的时候自己回收。当app 面临内存压力的时候。
在这样的情况下,你可以使用 @CanReleaseReferences.这个注解

@Documented@Retention ( RUNTIME ) @CanReleaseReferences@Scope public @interface MyScope {}
When you determine that you want to allow objects held in that scope to be deleted during garbage collection if they’re not currently being used by some other object, you can inject a  ReleasableReferenceManager  object for your scope and call  releaseStrongReferences()  on it, which will make the component hold a  WeakReference  to the object instead of a strong reference:
@Inject @ForReleasableReferences ( MyScope . class ) ReleasableReferences myScopeReferences ; void lowMemory () { myScopeReferences . releaseStrongReferences (); }

当你觉得让你持有对象,在现在没有被其他对象引用的时候。当gc的时候被回收掉,你可以注入一个
ReleasableReferenceManager对象,并且调用 releaseStrongReferences() 方法。这样manager对象就会将强方法改为软引用。
If you determine that the memory pressure has receded, then you can restore the strong references for any cached objects that have not yet been deleted during garbage collection by calling  restoreStrongReferences() :
void highMemory () { myScopeReferences . restoreStrongReferences (); }

如果你觉得内存压力变小了。你可以恢复强引用。通过调用这个方法。
它将会把还没被gc释放的的对象恢复。




Lazy injections
Sometimes you need an object to be instantiated lazily. For any binding  T , you can create a  Lazy<T>  which defers instantiation until the first call to  Lazy<T> ’s  get()  method. If  T  is a singleton, then  Lazy<T>  will be the same instance for all injections within the  ObjectGraph . Otherwise, each injection site will get its own  Lazy<T>  instance. Regardless, subsequent calls to any given instance of  Lazy<T>  will return the same underlying instance of  T .

有些时候,你希望你的对象可以懒加载,对于任何对象类型,你都可以创建一个 Lazy<T> 来实现懒加载,知道第一次 get()被调用,这个对象才会实例化。 如果T是单例,那么对象图中的所以注入都会只有一个实例。其他情况下,所有的注入都会拥有各自的T, 不管怎么样,随后的调用都会获取到相同的T的实例。

class GrindingCoffeeMaker { @Inject Lazy < Grinder > lazyGrinder ; public void brew () { while ( needsGrinding ()) { // Grinder created once on first call to .get() and cached. lazyGrinder . get (). grind (); } } }


Provider injections
Sometimes you need multiple instances to be returned instead of just injecting a single value. While you have several options (Factories, Builders, etc.), one option is to inject a  Provider<T>  instead of just  T . A  Provider<T>  invokes the  binding logic  for  T  each time  .get()  is called. If that binding logic is an  @Inject  constructor, a new instance will be created, but a  @Provides  method has no such guarantee.

很多时候,你需要注入一个值,但是可能返回多种实例。 当你有多个选项的时候,比如工厂模式,建造者模式。 你可以更改其中的选项T,然后会调用其不同情景下的绑定逻辑。
如果绑定逻辑实在构造器上,那么会得到一个新的实例。但是 注解方法,无法保证。

class BigCoffeeMaker { @Inject Provider < Filter > filterProvider ; public void brew ( int numberOfPots ) { ... for ( int p = 0 ; p < numberOfPots ; p ++) { maker . addFilter ( filterProvider . get ()); //new filter every time. maker . addCoffee (...); maker . percolate (); ... } } }
Note:  Injecting  Provider<T>  has the possibility of creating confusing code, and may be a design smell of mis-scoped or mis-structured objects in your graph. Often you will want to use a  factory  or a  Lazy<T>  or re-organize the lifetimes and structure of your code to be able to just inject a  T . Injecting  Provider<T>  can, however, be a life saver in some cases. A common use is when you must use a legacy architecture that doesn’t line up with your object’s natural lifetimes (e.g. servlets are singletons by design, but only are valid in the context of request-specfic data).

注意,使用Provider<T>注解,可能会让代码变得混乱。让其失去结构性和周期性。
所以你经常想用工厂模式,或者lazy<T> 注解 来有组织的注入对象。而替代Provider<T>
一个共同的用法,就是当你必须使用一个遗留的结构。 这个结构与你已有的对象生命周期完全无关。
比如servlet 被设置成单例的,但是这个仅仅在同一个请求数据的上下文数据时有效。


Qualifiers
Sometimes the type alone is insufficient to identify a dependency. For example, a sophisticated coffee maker app may want separate heaters for the water and the hot plate.
In this case, we add a  qualifier annotation . This is any annotation that itself has a  @Qualifier  annotation. Here’s the declaration of  @Named , a qualifier annotation included in  javax.inject :

有的时候,单独使用某种类型来识别某种依赖,是很难实现的。
比如,一个复杂的coffee maker 应用可能会需要多个分离的热水炉子和盘子。
基于这种情况,我们添加了Qualifier 这个注解。 所有的注解都用到了qualifier这个注解。
下面就是一个javax.inject包中自带的 @Name注解的例子。

@Qualifier@Documented@Retention ( RUNTIME ) public @interface Named { String value () default "" ; }
You can create your own qualifier annotations, or just use  @Named . Apply qualifiers by annotating the field or parameter of interest. The type and qualifier annotation will both be used to identify the dependency.

你可以创建你自己的Qualifier注解。或者就使用@Name 来注解那些你想注解的字段或者参数。
类型和qualifier注解都是用来标示依赖的。

class ExpensiveCoffeeMaker { @Inject @Named ( "water" ) Heater waterHeater ; @Inject @Named ( "hot plate" ) Heater hotPlateHeater ; ... }
Supply qualified values by annotating the corresponding  @Provides  method.
给@Provides方法添加qualified注解。

@Provides @Named ( "hot plate" ) static Heater provideHotPlateHeater () { return new ElectricHeater ( 70 ); } @Provides @Named ( "water" ) static Heater provideWaterHeater () { return new ElectricHeater ( 93 ); }
Dependencies may not have multiple qualifier annotations.

每个依赖不能拥有多个qualifier注解。


Optional bindings


If you want a binding to work even if some dependency is not bound in the component, you can add a  @BindsOptionalOf  method to a module:

可选绑定,如果你想绑定一些不确定的依赖。你可以使用 @BindsOptionalOf方法给一个module。

@BindsOptionalOf abstract CoffeeCozy optionalCozy ();
That means that  @Inject  constructors and members and  @Provides  methods can depend on an  Optional<CoffeeCozy>  object. If there is a binding for  CoffeeCozy  in the component, the  Optional  will be present; if there is no binding for  CoffeeCozy , the  Optional  will be absent.

这句代码的意思是。 @inject的构造器和 @provides的方法都是依赖于 这个 optional<CoffeCozy>对象的。
如果有这个依赖的组件,那么这个optional对象将会存在,否则,将不存在。

Specifically, you can inject any of the following:
  • Optional<CoffeeCozy>
  • Optional<Provider<CoffeeCozy>>
  • Optional<Lazy<CoffeeCozy>>
  • Optional<Provider<Lazy<CoffeeCozy>>>
(You could also inject a  Provider  or  Lazy  or  Provider  of  Lazy  of any of those, but that isn’t very useful.)
An optional binding that is absent in one component can be present in a subcomponent if the subcomponent includes a binding for the underlying type.
You can use either Guava’s  Optional  or Java 8’s  Optional .



你也可以使用 Optional注解来修饰一个 provider 或者 lazy 或者其他的类型。但是这不是很有用。
可选绑定 一般用在一个子组件包含有不确定的类型的情况下。 类似的用法你还可以使用guava 或者Java8 的optional。


Binding Instances
Often you have data available at the time you’re building the component. For example, suppose you have an application that uses command-line args; you might want to bind those args in your component.
Perhaps your app takes a single argument representing the user’s name that you’d like to inject as  @UserName String . You can add a method annotated  @BindsInstance  to the component builder to allow that instance to be injected in the component.

绑定实例
有的时候,你会有想把数据绑定到组件的需求。 比如假如你的应用需要使用命令行参数。 你可能会想要绑定这些参数到你的组件。 或许你的应用想要把一个单独的参数绑定到@UserName字符串。 你可以给一个方法添加@BindsInstance注解 使这个组件builder允许这个实例被注入到组件中。

@Component ( modules = AppModule . class ) interface AppComponent { App app (); @Component . Builder interface Builder { @BindsInstance Builder userName ( @UserName String userName ); AppComponent build (); } }
Your app then might look like
public static void main ( String [] args ) { if ( args . length > 1 ) { exit ( 1 ); } App app = DaggerAppComponent . builder () . userName ( args [ 0 ]) . build () . app (); app . run (); }
In the above example, injecting  @UserName String  in the component will use the instance provided to the  Builder  when calling this method. Before building the component, all  @BindsInstance  methods must be called, passing a non-null value (with the exception of  @Nullable  bindings below).

在上面的例子中。如果你想注入@username字段进入你的组件。你调用builder方法时,必须提供所有的@bindinstance 注解的方法的参数。 而且不能穿空值。

If the parameter to a  @BindsInstance  method is marked  @Nullable , then the binding will be considered “nullable” in the same way as a  @Provides  method is nullable: injection sites must also mark it  @Nullable , and  null  is an acceptable value for the binding. Moreover, users of the  Builder  may omit calling the method, and the component will treat the instance as  null .

如果@BindInstance方法如果被标记为 nullable。那么这个绑定就会看做是 @priovides注解提供一个nullable. 并且 这个注入站点也会被被标为@nullable. 绑定时也可以接受null。
用户的builder使用的时候也可以忽略这个方法。并且组件也会认为这个实力为null.

@BindsInstance  methods should be preferred to writing a  @Module  with constructor arguments and immediately providing those values.

因此使用此注解方法时,最好立刻提供数值,并且将构造器标记为@module

Compile-time Validation
编译时验证

The Dagger  annotation processor  is strict and will cause a compiler error if any bindings are invalid or incomplete. For example, this module is installed in a component, which is missing a binding for  Executor :

dagger的注解处理器精确的处理注解。并且当编译失败或者不完整的时候会报错。
比如下面的这个module就缺少了绑定的executor


@Module class DripCoffeeModule { @Provides static Heater provideHeater ( Executor executor ) { return new CpuHeater ( executor ); } }
When compiling it,  javac  rejects the missing binding:
编译的时候,会有如下提示

[ERROR] COMPILATION ERROR :[ERROR] error: java.util.concurrent.Executor cannot be provided without an @Provides-annotated method.

Fix the problem by adding an  @Provides -annotated method for  Executor  to  any  of the modules in the component. While  @Inject @Module  and  @Provides  annotations are validated individually, all validation of the relationship between bindings happens at the  @Component  level. Dagger 1 relied strictly on  @Module -level validation (which may or may not have reflected runtime behavior), but Dagger 2 elides such validation (and the accompanying configuration parameters on  @Module ) in favor of full graph validation.


修改这个问题的方法是,给他所依赖的任何module 添加一个 @provides方法 来提供executor.
当@inject @module @provides 注解被分别验证的时候。所有的验证关系会绑定到@component级别。
dagger1 只依赖@module级别的校验。 (这将会导致一些运行行为被忽视)
dagger2 会校验整个对象图所有的有效性,包括module相关的配置。


Compile-time Code Generation
Dagger’s annotation processor may also generate source files with names like  CoffeeMaker_Factory.java  or  CoffeeMaker_MembersInjector.java . These files are Dagger implementation details. You shouldn’t need to use them directly, though they can be handy when step-debugging through an injection. The only generated types you should refer to in your code are the ones Prefixed with Dagger for your component.

dagger的注解处理器也会生成一些源文件 ,类似CoffeeMaker_Factory.java or CoffeeMaker_MembersInjector.java.
你不应该直接操作政协文件,虽然他们可以手动调试。你唯一需要修改的代码就是你component的前缀单词。

Using Dagger In Your Build
You will need to include the  dagger-2.X.jar  in your application’s runtime. In order to activate code generation you will need to include  dagger-compiler-2.X.jar  in your build at compile time. See the  README  for more information.


你需要 dagger-2.X.jar 来使用dagger 以及 dagger-compiler-2.X.jar来生成代码。 更多的信息可以看这里。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值