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

 有些情況需要將同一類型映射到不同的類實現,還是使用繪圖的例子.
IShape, Rectangle, MyRectangle, MySquare,有如下繼承關系:

 

我們可能需要將IShape 同時映射到MyRectangle 和MySquare ,這時可以使用Binding Annotation 來實現。 這時使用類型和annotation (標註)可以唯一確定一個Binding。Type 和annotation 對稱為Key(鍵)。

為瞭同時使用MyRectangle和MySequare,我們定義兩個annotation,如下

[java] import com.google.inject.BindingAnnotation; 
import java.lang.annotation.Target; 
import java.lang.annotation.Retention; 
import static java.lang.annotation.RetentionPolicy.RUNTIME; 
import static java.lang.annotation.ElementType.PARAMETER; 
import static java.lang.annotation.ElementType.FIELD; 
import static java.lang.annotation.ElementType.METHOD; 
  
… 
@BindingAnnotation 
@Target({ FIELD, PARAMETER, METHOD }) 
@Retention(RUNTIME) 
public @interface Rectangle { 

… 
  
@BindingAnnotation 
@Target({ FIELD, PARAMETER, METHOD }) 
@Retention(RUNTIME) 
public @interface Square { 

import com.google.inject.BindingAnnotation;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
 

@BindingAnnotation
@Target({ FIELD, PARAMETER, METHOD })
@Retention(RUNTIME)
public @interface Rectangle {
}

 
@BindingAnnotation
@Target({ FIELD, PARAMETER, METHOD })
@Retention(RUNTIME)
public @interface Square {
}
定義瞭兩個標註 @Rectangle, @Square, 至於@BindingAnnotation,@Target,@Retention你並不需要詳細瞭解,有興趣的可以參見Java Annotation tutorial .

簡單的說明如下:

@BindingAnnotation 通知這是一個Binding Annotation,如果將多個個標註應用到同一個元素時,Guice會報錯。
@Target({FIELD, PARAMETER, METHOD}) 表示這個標註可以應用到類成員變量,函數的參數或時方法。
@Retention(RUNTIME) 表示這個標註在程序運行時可以使用Reflection讀取。
創建一個BindingAnnotationsDemo 用來繪制兩個圖形:

[java] public class BindingAnnotationsDemo extends Graphics2DActivity{ 
  
 @Inject @Rectangle IShape  shape1; 
 @Inject @Square IShape  shape2; 
  
 protected void drawImage(){ 
  
 /**
 * The semi-opaque blue color in
 * the ARGB space (alpha is 0x78)
 */ 
 Color blueColor = new Color(0x780000ff,true); 
 /**
 * The semi-opaque green color in the ARGB space (alpha is 0x78)
 */ 
 Color greenColor = new Color(0x7800ff00,true); 
  
 graphics2D.clear(Color.WHITE); 
 graphics2D.Reset(); 
  
 SolidBrush brush=new SolidBrush(blueColor); 
  
 graphics2D.fill(brush,shape1); 
 AffineTransform at = new AffineTransform(); 
 at.translate(20, 20); 
 graphics2D.setAffineTransform(at); 
 brush=new SolidBrush(greenColor); 
 graphics2D.fill(brush,shape2); 
  
 } 
  

public class BindingAnnotationsDemo extends Graphics2DActivity{
 
 @Inject @Rectangle IShape  shape1;
 @Inject @Square IShape  shape2;
 
 protected void drawImage(){
 
 /**
 * The semi-opaque blue color in
 * the ARGB space (alpha is 0x78)
 */
 Color blueColor = new Color(0x780000ff,true);
 /**
 * The semi-opaque green color in the ARGB space (alpha is 0x78)
 */
 Color greenColor = new Color(0x7800ff00,true);
 
 graphics2D.clear(Color.WHITE);
 graphics2D.Reset();
 
 SolidBrush brush=new SolidBrush(blueColor);
 
 graphics2D.fill(brush,shape1);
 AffineTransform at = new AffineTransform();
 at.translate(20, 20);
 graphics2D.setAffineTransform(at);
 brush=new SolidBrush(greenColor);
 graphics2D.fill(brush,shape2);
 
 }
 
}
使用標註將shape1 綁定到MyRectangle, shape2綁定到MySquare,對應的Module 定義如下:

[java] public class Graphics2DModule extends AbstractAndroidModule{ 
  
 @Override 
 protected void configure() { 
  
 bind(IShape.class) 
 .annotatedWith(Rectangle.class) 
 .to(MyRectangle.class); 
  
 bind(IShape.class) 
 .annotatedWith(Square.class) 
 .to(MySquare.class); 
  
 } 

 

Inject 可以應用到Field (成員變量),Parameter (參數)或Method(方法),前面的例子都是應用到Field上,如果應用到參數可以有如下形式:

[java] @Inject 
public IShape getShape(@Rectangle IShape shape){ 
… 

@Inject
public IShape getShape(@Rectangle IShape shape){

}
如果你不想自定義Annotation,可以使用Guice自帶的@Name標註來解決同一類型綁定到不同實現的問題。

修改上面代碼:

[java]  //@Inject @Rectangle IShape  shape1;  
//@Inject @Square IShape  shape2;  
  
@Inject @Named("Rectangle") IShape shape1; 
@Inject @Named("Square") IShape shape2; 
//@Inject @Rectangle IShape  shape1;
//@Inject @Square IShape  shape2;
 
@Inject @Named("Rectangle") IShape shape1;
@Inject @Named("Square") IShape shape2;
修改綁定如下:

[java] view plaincopyprint? //bind(IShape.class)  
//.annotatedWith(Rectangle.class)  
//.to(MyRectangle.class);  
  
//bind(IShape.class)  
//.annotatedWith(Square.class)  
//.to(MySquare.class);  
  
bind(IShape.class) 
 .annotatedWith(Names.named("Rectangle")) 
 .to(MyRectangle.class); 
bind(IShape.class) 
 .annotatedWith(Names.named("Square")) 
 .to(MySquare.class); 
//bind(IShape.class)
//.annotatedWith(Rectangle.class)
//.to(MyRectangle.class);
 
//bind(IShape.class)
//.annotatedWith(Square.class)
//.to(MySquare.class);
 
bind(IShape.class)
 .annotatedWith(Names.named("Rectangle"))
 .to(MyRectangle.class);
bind(IShape.class)
 .annotatedWith(Names.named("Square"))
 .to(MySquare.class);

 

這種方法簡單,但編譯器無法檢測字符串,比如將”Square”錯寫為”Sqare”,編譯器無法查出這個錯誤,此時到運行時才可能發現 shape2 無法註入,因此建議盡量少用Named.

本例下載:http://up.aiwalls.com/2012/0504/20120504095233906.zip
 

 

摘自 引路蜂移動軟件

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。