Android RoboGuice 使用指南(5):Binding Annotations

jerry Android 2015年08月24日 收藏

有些情况需要将同一类型映射到不同的类实现,还是使用绘图的例子.

IShape, Rectangle, MyRectangle, MySquare,有如下继承关系:

我们可能需要将IShape 同时映射到MyRectangle 和MySquare ,这时可以使用Binding Annotation 来实现。 这时使用类型和annotation (标注)可以唯一确定一个Binding。Type 和annotation 对称为Key(键)。

为了同时使用MyRectangle和MySequare,我们定义两个annotation,如下

  1. import com.google.inject.BindingAnnotation;
  2. import java.lang.annotation.Target;
  3. import java.lang.annotation.Retention;
  4. import static java.lang.annotation.RetentionPolicy.RUNTIME;
  5. import static java.lang.annotation.ElementType.PARAMETER;
  6. import static java.lang.annotation.ElementType.FIELD;
  7. import static java.lang.annotation.ElementType.METHOD;
  8.  
  9. ...
  10. @BindingAnnotation
  11. @Target({ FIELD, PARAMETER, METHOD })
  12. @Retention(RUNTIME)
  13. public @interface Rectangle {
  14. }
  15. ...
  16.  
  17. @BindingAnnotation
  18. @Target({ FIELD, PARAMETER, METHOD })
  19. @Retention(RUNTIME)
  20. public @interface Square {
  21. }

定义了两个标注 @Rectangle, @Square, 至于@BindingAnnotation,@Target,@Retention你并不需要详细了解,有兴趣的可以参见Java Annotation tutorial .

简单的说明如下:

  • @BindingAnnotation 通知这是一个Binding Annotation,如果将多个个标注应用到同一个元素时,Guice会报错。
  • @Target({FIELD, PARAMETER, METHOD})  表示这个标注可以应用到类成员变量,函数的参数或时方法。
  • @Retention(RUNTIME) 表示这个标注在程序运行时可以使用Reflection读取。

创建一个BindingAnnotationsDemo 用来绘制两个图形:

  1. public class BindingAnnotationsDemo extends Graphics2DActivity{
  2.  
  3. @Inject @Rectangle IShape  shape1;
  4. @Inject @Square IShape  shape2;
  5.  
  6. protected void drawImage(){
  7.  
  8. /**
  9. * The semi-opaque blue color in
  10. * the ARGB space (alpha is 0x78)
  11. */
  12. Color blueColor = new Color(0x780000ff,true);
  13. /**
  14. * The semi-opaque green color in the ARGB space (alpha is 0x78)
  15. */
  16. Color greenColor = new Color(0x7800ff00,true);
  17.  
  18. graphics2D.clear(Color.WHITE);
  19. graphics2D.Reset();
  20.  
  21. SolidBrush brush=new SolidBrush(blueColor);
  22.  
  23. graphics2D.fill(brush,shape1);
  24. AffineTransform at = new AffineTransform();
  25. at.translate(20, 20);
  26. graphics2D.setAffineTransform(at);
  27. brush=new SolidBrush(greenColor);
  28. graphics2D.fill(brush,shape2);
  29.  
  30. }
  31.  
  32. }

使用标注将shape1 绑定到MyRectangle, shape2绑定到MySquare,对应的Module 定义如下:

  1. public class Graphics2DModule extends AbstractAndroidModule{
  2.  
  3. @Override
  4. protected void configure() {
  5.  
  6. bind(IShape.class)
  7. .annotatedWith(Rectangle.class)
  8. .to(MyRectangle.class);
  9.  
  10. bind(IShape.class)
  11. .annotatedWith(Square.class)
  12. .to(MySquare.class);
  13.  
  14. }
  15. }

Inject 可以应用到Field (成员变量),Parameter (参数)或Method(方法),前面的例子都是应用到Field上,如果应用到参数可以有如下形式:

  1.  
  2. @Inject
  3. public IShape getShape(@Rectangle IShape shape){
  4. ...
  5. }

如果你不想自定义Annotation,可以使用Guice自带的@Name标注来解决同一类型绑定到不同实现的问题。

修改上面代码:

  1. //@Inject @Rectangle IShape  shape1;
  2. //@Inject @Square IShape  shape2;
  3.  
  4. @Inject @Named("Rectangle") IShape shape1;
  5. @Inject @Named("Square") IShape shape2;

修改绑定如下:

  1. //bind(IShape.class)
  2. //.annotatedWith(Rectangle.class)
  3. //.to(MyRectangle.class);
  4.  
  5. //bind(IShape.class)
  6. //.annotatedWith(Square.class)
  7. //.to(MySquare.class);
  8.  
  9. bind(IShape.class)
  10. .annotatedWith(Names.named("Rectangle"))
  11. .to(MyRectangle.class);
  12. bind(IShape.class)
  13. .annotatedWith(Names.named("Square"))
  14. .to(MySquare.class);

这种方法简单,但编译器无法检测字符串,比如将”Square”错写为”Sqare”,编译器无法查出这个错误,此时到运行时才可能发现 shape2 无法注入,因此建议尽量少用Named.