..
最近在看大神的源碼,發現有很多使用註解的地方,調查下相關的使用原理記錄一下。_
註解
Java 註解(Annotation)又稱 Java 標註,是 JDK5.0 引入的一種註釋機制。
Java 語言中的類、方法、變量、參數和包等都可以被標註。
和 Javadoc 不同,Java 標註可以通過反射獲取標註內容。在編譯器生成類文件時,標註可以被嵌入到字節碼中。Java 虛擬機可以保留標註內容,在運行時可以獲取到標註內容 。
例如:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
元註解
元註解,專職負責註解其他的註解。
元註解 | 說明 | 取值 |
---|---|---|
@Target | 表示該註解可以用在什麼地方 | ElementType.ANNOTATION_TYPE 可以應用於註釋類型。ElementType.CONSTRUCTOR 可以應用於構造函數。ElementType.FIELD 可以應用於字段或屬性。ElementType.LOCAL_VARIABLE 可以應用於局部變量。ElementType.METHOD 可以應用於方法級註釋。ElementType.PACKAGE 可以應用於包聲明。ElementType.PARAMETER 可以應用於方法的參數。ElementType.TYPE 可以應用於類的任何元素。 |
@Retention | 表示需要在什麼級別保存該註解信息 | 1.SOURCE:在源文件中有效(即源文件保留)2.CLASS:在class文件中有效(即class保留)3.RUNTIME:在運行時有效(即運行時保留) |
@Documented | 表示將此註解包含在Javadoc中 | 無 |
@Inherited | 表示允許子類繼承父類中的註解 | 無 |
Android註解
本來在Android系統源碼中/frameworks/base/core/java/android/annotation中是有很多的註解的,但是,他們都是系統源碼用的註解,不是給我們這種開發人員用的,因爲所有的註解的註釋上都有@hide註釋。
/*
* {@hide}
*/
@Documented
@Retention(SOURCE)
@Target({METHOD, PARAMETER, FIELD})
public @interface AnyRes {
}
Android系統提供的SDK中,只有兩個原生註解。位於android.annotation包中:
- @TargetApi 使高版本API的代碼在低版本SDK不報錯。
- @SuppressLint 使用此標註讓Lint忽略指定的警告。
自定義註解
首先自定義註解InjectDIYLayout , 這裏爲了簡單示例用了運行時註解,並採用反射方法調用執行。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectDIYLayout {
int value();
}
所有的註解類型都繼承自這個普通的接口(Annotation)
實現工具類,在BaseActivity中的onCreate中初始化。InjectDIYUtils .inject(this);
public class InjectDIYUtils {
private static final String TAG = "InjectDIYUtils";
public static void inject(Object context){
injectDIYLayout (context);
}
}
通過類getAnnotation得到此類註釋的註解,經打印可以判斷是否此註解。然後通過反射獲取到setContentView,並用反射方法的invoke調用,傳入註解中的layout值。
private static void injectDIYLayout (Object context) {
Class<?> aClass = context.getClass();
InjectDIYLayout annotation = aClass.getAnnotation(InjectDIYLayout.class);
Log.e(TAG, "injectLayout: annotation.value()="+annotation.value());
try {
Method contentView = aClass.getMethod("setContentView", int.class);
try {
Object invoke = contentView.invoke(context, annotation.value());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
使用舉例:
@InjectDIYLayout(R.layout.activity_main)
public class MainActivity extends BaseActivity {