編輯:關於Android編程
都說Annotation的運用非常簡單,但真正我們需要下手實現的的時候,有的時候就不知道從哪裡下手,為什麼我們覺得很簡單的東西,但卻無法下手呢?
原因只有一個,我們對它的使用非常少,但對於寫框架的人來說Annotation卻使用的頻率非常高。那既然我們平時用的非常少,我寫這篇blog就沒什麼意義了,的確,那我也只當是給大家做個查閱的文檔。不過我還是希望大家能通過這篇blog,加強對Annotation的理解,這篇blog省去了Annotation不必要的知識點,就像慕課網所說的只學有用的。
進入主題:
一、先分析源碼:
只需要知道一下四個類就行了
1、
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
這個注解的作用是當我們需要聲明自定義的Annotation是,需要用到此注解,還需要設置value的值;value的值的作用,就需要講第二個類的時候說明,使用方法,可以參考此類本身,直接在自定義的Annotation上加上@Retention(RetentionPolicy.RUNTIME),或者另一種寫法@Retention(value = RetentionPolicy.RUNTIME),效果是一樣的,這裡需要注意一點的是,Annotation可以用自己來對自己進行注解說明。
2、
public enum RetentionPolicy {
/**
* Annotation is only available in the source code.
*/
SOURCE,
/**
* Annotation is available in the source code and in the class file, but not
* at runtime. This is the default policy.
*/
CLASS,
/**
* Annotation is available in the source code, the class file and is
* available at runtime.
*/
RUNTIME
}
這個是一個枚舉類型,功能是控制Annotation的級別,值越大,權限越高,Annotation的作用范圍越大,下面分別解釋三個級別的作用范圍:
SOURCE:只在源文件此注解中有效,也就是,只要代碼已經編譯過了,權限被聲明為SOURCE的Annotation就無效;
CLASS: 文件或者代碼已經編譯了,這個時候還有效,當代碼跑起來了的時候,就沒有效果了;
RUNTIME:這個相當於最大權限,記住可用於任何時候,而我們在寫代碼的時候,都是希望在運行時候用,所以,一般情況下我們都是聲明為RUNTIME權限。
3、
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
這又是一個注解類,這個類的作用也是在我們自定義Annotation的時候聲明,然後確定自定義Annotation的作用類型是那個地方,它的取值就是下一個類所要講的,用法與Retention注解一樣,確切的說所有的Annotation都是這樣使用
4、
public enum ElementType {
/**
* Class, interface or enum declaration.
*/
TYPE,
/**
* Field declaration.
*/
FIELD,
/**
* Method declaration.
*/
METHOD,
/**
* Parameter declaration.
*/
PARAMETER,
/**
* Constructor declaration.
*/
CONSTRUCTOR,
/**
* Local variable declaration.
*/
LOCAL_VARIABLE,
/**
* Annotation type declaration.
*/
ANNOTATION_TYPE,
/**
* Package declaration.
*/
PACKAGE
}
這個類就是確定Annotation的作用位置,每個不同的值,對應的位置不相同
/**
* 作用於類,接口或枚舉
*/
TYPE,
/**
* 作用於字段,也就是成員變量.
*/
FIELD,
/**
* 作用於方法.
*/
METHOD,
/**
* 參數.
*/
PARAMETER,
/**
* 構造方法.
*/
CONSTRUCTOR,
/**
* 本地變量.
*/
LOCAL_VARIABLE,
/**
* 注解.
*/
ANNOTATION_TYPE,
/**
* 包名.
*/
PACKAGE
我只是把英文翻譯了一遍,如果有錯請指正。
基本用法介紹完了,接下來開始自定義Annotation
二、自定義Annotation
通過Android studio創建Annotation類,創建類的時候可以直接指定Annotation類型,這樣創建出來的文件如下:
/**
* Created by moon.zhong on 2015/2/14.
*/
public @interface TestAnnotation {
}
和接口非常像,只不過多了一個@,根據剛剛所講,需要再類上加上@Retention(RetentionPolicy.RUNTIME)來確定權限的大小,這裡直接采用最大權限,並指定作用的類型@Target(ElementType.METHOD),這裡指定作用於方法上面
自定義Annotation就完成了。
三、使用Annotation
寫任何代碼都不是用來看的,所以我們一定得知道如何使用它。
Annotation往往是跟反射結合起來使用的,我們在學習反思的時候,知道反射裡面很多方法獲取Annotation的值,也可以得出這樣一個結論,用到了Annotation的情況下,基本上就用到了反射,我們常說的一句話,無反射,不框架,這也是為什麼但大部分框架都大量使用Annotation的原因
這裡也是用反射的列子來說明Annotation的使用
編寫好自定義的Annotation,讓其作用范圍在類上面,
/**
* Created by moon.zhong on 2015/2/14.
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.TYPE)
public @interface ClassAnnotation {
}
定義好一個Bean的類,加上注解
/**
* Created by moon.zhong on 2015/2/14.
*/
@ClassAnnotation
public class Bean {
}
通過反射來查看注解是否已經能正常使用
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Class mClass = Bean.class ;
Annotation annotation[] = mClass.getAnnotations() ;
for (Annotation a : annotation){
Log.v("zgy","====getAnnotations===="+a.annotationType()) ;
}
}
}
最後打印的log信息:zgy﹕ ====getAnnotations====interface moon.annotationdemo.ClassAnnotation
再來看看怎麼給自定義的Annotation設置值,像@Retention(RetentionPolicy.RUNTIME)一樣後面可以跟上一個值。在上面看log信息的時候,你是否發現了多打印了一個interface,而後面緊跟著的才是Annotation的全名,其實Annotation本省就是接口的一種,所以在聲明變量的時候,只需定義一個抽象方法即可,不需要實現,完全可以參照 public @interface Retention
/**
* Created by moon.zhong on 2015/2/14.
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.TYPE)
public @interface ClassAnnotation {
String print() ;
}www.2cto.com
/**
* Created by moon.zhong on 2015/2/14.
*/
@ClassAnnotation(print = "annotation")
public class Bean {
}
使用也是一樣的同 @interface Retention ,在Bean的類名上面加上@ClassAnnotation(print = “annotation”),這裡有一點需要注意,不能寫成@ClassAnnotation(“annotation”),因為這裡定義的方法是print(),如果換成value() 就可以省略。
/**
* Created by moon.zhong on 2015/2/14.
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.TYPE)
public @interface ClassAnnotation {
String value() ;
}
/**
* Created by moon.zhong on 2015/2/14.
*/
@ClassAnnotation("annotation")
public class Bean {
}
來測試下:
for (Annotation a : annotation){
Log.v("zgy","====print===="+((ClassAnnotation)a).print()) ;
}
打印log的信息 zgy﹕ ====print====annotation
說明我們已經拿到了所設置的值,那麼接下來要實現什麼要的功能就看大家的智慧了。
四、總結:
老規矩,就像燒菜最後都要澆汁,這裡來做個總結,在定義Annotation的時候,需要注意兩點,一、通過@Retention(RetentionPolicy.RUNTIME)注解來確定聲明的Annotation的作用權限,這裡一般設為最大就可以了;二、通過@Target(ElementType.ANNOTATION_TYPE)注解來確定此注解的作用對象是誰。還有一點需要注意,自定義的Annotation如果定義了抽象方法,如果抽象方法名為value的時候,使用的時候可以省略,其他時候不能省略,個人建議,都加上。
今天我們實現一個直接繼承於View的全新控件。大家都知道音樂播放器吧,在點擊一首歌進行播放時,通常會有一塊區域用於顯示音頻條,我們今天就來學習下,播放器音頻條的實現。首先
由於Google編譯Android源碼使用的操作系統是Ubuntu,所以此處本人也是安裝Ubuntu操作系統。五筆法安裝Ubuntu系統固然方便簡單,可缺陷是安裝的系統的
主要講解Android Studio中生成aar文件以及本地方式使用aar文件的方法。 在Android Studio中對一個自己庫進行生成操作時將會同時生成*.jar與
通過Espresso測試錄制器來創建UI注意:Espresso測試記錄器在Android Stuido 2.2中只是一個測試版。工具Espresso測試錄制器可以讓你不寫