Android中註解的使用
如果你是一名安卓開發者,你也一定聽過大名鼎鼎的網絡請求框架Retrofit。它將網絡請求的方式以註解的形式展現,極大的提高了代碼的可讀性,同時網絡請求集中寫在一個interface中提高了代碼的可維護性。除此之外,例如Dagger , GreenDao,ButterKnife等等 也是大量運營了註解。為什麽這些知名的開源項目如此青睞註解?
在註解使用之前,xml被廣泛用於描述原數據,但是在使用xml越來越長之後,開發人員意識到使用xml耦合性太高。於是在java 5.0 的版本,註解(Annotation)出現了。目前xml 與 Annotation 共同使用著,發揮著他們的長處。我們該如何使用註解呢?其實註解使用起來非常簡單。一個自定義註解可以被四個java 規定的原註解所描述這四個原註解分別是:@Documented @Retention @Target @Inherited 。
@Documented -表示是否將註解信息添加在java文檔中。
@Retention -定義該註解的生命周期。
RetentionPolicy.SOURCE – 在編譯階段丟棄。這些註解在編譯結束之後就不再有任何意義,所以它們不會寫入字節碼。@Override, @SuppressWarnings都屬於這類註解。
RetentionPolicy.CLASS – 在類加載的時候丟棄。在字節碼文件的處理中有用。註解默認使用這種方式。
RetentionPolicy.RUNTIME– 始終不會丟棄,運行期也保留該註解,因此可以使用反射機制讀取該註解的信息。我們自定義的註解通常使用這種方式。
@Target -表示該註解用於什麽地方。如果不明確指出,該註解可以放在任何地方。以下是一些可用的參數。需要說明的是:屬性的註解是兼容的,如果你想給7個屬性都添加註解,
僅僅排除一個屬性,那麽你需要在定義target包含所有的屬性。
ElementType.TYPE:用於描述類、接口或enum聲明
ElementType.FIELD:用於描述實例變量
ElementType.METHOD
ElementType.PARAMETER
ElementType.CONSTRUCTOR
ElementType.LOCAL_VARIABLE
ElementType.ANNOTATION_TYPE 另一個註釋
ElementType.PACKAGE 用於記錄java文件的package信息
@Inherited -定義該註釋和子類的關系
話不多說我們來實戰一下。在我們開始寫項目的時候通常都會封裝一個BaseActivity,每個面向界面的Activity中都會指向一個xml 界面文件,也就是Activity 與 xml是綁定關系的。這樣我們的註解就能派上用場了,我們可以通過註解將xml 綁定到對應的Activity中。一個Activity類中綁定一個layout 那麽我們的註解描述類型就是TYPE。這個綁定效果一定是作用到運行時的,所以有了如下代碼。
1 @Retention(RetentionPolicy.RUNTIME) 2 @Target(ElementType.TYPE) 3 @Documented 4 public @interface BindLayout { 5 @LayoutRes 6 int value(); 7 8 }
我們通過反射獲取到這個註解中傳入的xml數據,將他綁定在Activity中。代碼如下:
1 private static void bindActivityLayout(Activity activity) { 2 Class aClass = activity.getClass(); 3 BindLayout annotation = (BindLayout) aClass.getAnnotation(BindLayout.class); 4 if (annotation != null) { 5 activity.setContentView(annotation.value()); 6 ButterKnife.bind(activity); 7 } 8 }
我們只要在Activity中的OnCreate初始化一下,就能夠輕松實現綁定。
@BindLayout(R.layout.activity_xx) public class XXActivity extends Activity { @Override protected void onCreate() { MoBind moBind = new MoBind(); moBind.bindActivity(this); } ... }
比較正確的做法是將綁定方法放入BaseActivity中,讓我們的子類繼承於他,這樣一對一的關系變的簡潔明了。當然,不只只是這樣,你可以開發新的用途,例如,我們需要在界面中綁定其他View做一下操作,比如顯示一個空的界面或者顯示一個自定義的Dialog。
通過註解,也可以快速的綁定,還記得我們的原註解Targe可以修飾一個變量,於是綁定一個其他View在Activity中就可以這麽做:
1 @Retention(RetentionPolicy.RUNTIME) 2 @Target(ElementType.FIELD) 3 @Documented 4 public @interface BindOthersView { 5 @LayoutRes int value(); 6 }
我們一樣通過反射調用:
1 private static void bindActivityView(Activity activity) { 2 Field[] declaredFields = activity.getClass().getDeclaredFields(); 3 if (declaredFields != null && declaredFields.length > 0) { 4 for (Field f : declaredFields) { 5 BindOthersView annotation = f.getAnnotation(BindOthersView.class); 6 if (annotation != null) { 7 View inflate = LayoutInflater.from(activity).inflate(annotation.value(), null); 8 if (inflate != null) { 9 try { 10 f.setAccessible(true); 11 f.set(activity, inflate); 12 } catch (IllegalAccessException e) { 13 e.printStackTrace(); 14 } 15 } 16 } 17 } 18 } 19 20 }
我們只需要在BaseActivity中的OnCreate 中初始化一次,就可以在它的子類中隨意綁定其他View(代碼中已經做了初始化,請放心使用)。
1 @BindOthersView(R.layout.empty_view)
2 View emptyView;
怎麽樣,實現起來是不是非常簡單,總結起來就是三個步驟,定義註解,解析註解,使用註解。快去定義你自己的註解,讓你的代碼變得簡介且逼格滿滿吧。
Android中註解的使用