Android自定義注解(一)

為什么要寫這個祈远,因?yàn)榍岸螘r(shí)間看了一下AOP相關(guān)的一些內(nèi)容膨处,然后也是太久沒寫注解,看得有點(diǎn)那啥不順暢抑党,所以想對注解做個總結(jié)润绎。

一.JAVA自帶的注解

(1)Override 覆蓋
(2)Deprecated 標(biāo)記過期方法
(3)SuppressWarnings 屏蔽警告

二.自定義注解

1.定義

我這里寫個demo自定義一個注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface BindView {
    int value() default -1;
}

可以看出注解用@interface來標(biāo)志撬碟。

2.元注解

可以看出在上邊的定義中,上面還有兩個注解莉撇,這些被稱為元注解呢蛤,什么是元注解,簡單來說就是描述注解的注解
還有什么元數(shù)據(jù)的棍郎,元什么什么的其障,這個元其實(shí)不太好解釋,我記得之前看過一個元數(shù)據(jù)的描述涂佃,英文是 data about data励翼,這個元有這個about的那種感覺

元注解有4種
(1)@Retention 用來描述周期,Retention 有“保持時(shí)間”的意思巡李,這個屬性可以選三個值
SOURCE表示只在源碼中有用抚笔,編譯就沒用了。
CLASS表示在編譯中可用侨拦,運(yùn)行就沒用了。
RUNTIME表示運(yùn)行時(shí)可用辐宾。
這三種的區(qū)別解釋起來很麻煩狱从,總之一搬我們都是使用RUNTIME

(2)@Target 用來描述作用域,Target有目標(biāo)的意思叠纹,你這個注解要給哪個目標(biāo)修飾季研,這個屬性可以選以下的值
CONSTRUCTOR用于描述構(gòu)造器
FIELD用于描述域
LOCAL_VARIABLE用于描述局部變量
METHOD用于描述方法
PACKAGE用于描述包
PARAMETER用于描述參數(shù)
這個就是說,你允許把注解寫在什么地方誉察。這個屬性是可以多選的与涡,比如@Target({ElementType.FIELD, ElementType.METHOD})

(3)@Inherited 描述是否可以為繼承,默認(rèn)是false

(4)@Documented 描述是否會保存到 Javadoc 文檔中

一般我們只會用到前面兩個持偏,所以后面兩個我就不解釋了驼卖。

3.注解的值

可以給注解設(shè)置值,比如說我上面的代碼鸿秆,就在注解里寫了個

int value() default -1;

表示在使用注解時(shí)需要傳一個整形的值

@BindView(R.id.tv)
TextView textView;

我這傳了個R.id.tv就是一個整形的值酌畜。只有一個值的時(shí)候,必須以** value()**來命名卿叽,然后調(diào)用時(shí)就直接傳就行桥胞。我還是分情況來說吧恳守。

(1)不需要傳值的情況

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface BindView {

}

調(diào)用

@BindView
TextView textView;

(2)傳一個值的情況
就是我上面寫的代碼

(3)傳多個值的情況

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface BindView {
    int age;
    String name;
}

調(diào)用

@BindView(age = 18, name = "JackMa")
TextView textView;

最后,這個default 表示設(shè)置默認(rèn)值的意思贩虾。

三.調(diào)用注解

上面我們創(chuàng)建出了注解并定義好催烘,然后我們需要調(diào)用這個注解,那怎么調(diào)用呢缎罢,一般我們調(diào)用一個類或接口都是new 出來伊群,但是這東西怎么看都覺得new不出來吧,所以我們需要用反射來獲取到注解的對象屁使,然后進(jìn)行調(diào)用

我不想去講反射的內(nèi)容在岂,不然就沒完了。就說個思路蛮寂,需要用到哪個方法可以去查api蔽午。
注解在Java中就是Annotation懂吧,所以在反射中和Annotation相關(guān)的方法都是和注解相關(guān)的方法酬蹋。

比如說獲取注解及老,我就可以調(diào)用.getAnnotation(BindView.class)
再比如說我判斷注解存在不,可以調(diào)用isAnnotationPresent()
總之你只要記住注解是Annotation范抓,之后你不管是在反射中還是在哪里找和注解相關(guān)的方法骄恶,都先往Annotation這個名詞相關(guān)的地方找準(zhǔn)沒錯。

如果你不懂反射這里說再多也沒有匕垫。

四.案例

其實(shí)說了這么多僧鲁,到底哪里需要使用到注解呢,如果不使用到象泵,講它有啥用寞秃,我個人是目前接觸到AOP涉及注解比較頻繁,其它時(shí)候偶惠,比如說ButterKnife春寿,Dagger,Retrofit等等這些主流的框架都會用到注解忽孽,包括java后臺绑改,我接觸過spring會涉及到IOC啊AOP啊這些思想用java來實(shí)現(xiàn)也是用到注解比較多,所以可以來寫個小demo試試兄一。

不如就仿照ButterKnife吧厘线,我之前沒看過ButterKnife的源碼啊,我就按照我學(xué)會的注解的知識和ButterKnife的調(diào)用方法來仿寫個ButterKnife

1.首先定義注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface BindView {
    int value() default -1;
}

定義注解瘾腰,要求傳個資源進(jìn)來皆的,默認(rèn)是-1

2.按照ButterKnife的調(diào)用的樣子來寫調(diào)用的地方
public class MainActivity extends AppCompatActivity {

    @BindView(R.id.tv)
    TextView textView;
    @BindView(R.id.btn)
    Button btn;

    String yyy = "aasdasdas";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        textView.setText("wwwwwwwwwwwwww");
        btn.setText("btn");
    }
}

發(fā)現(xiàn)ButterKnife調(diào)用的地方使用這 ButterKnife.bind(this); 那我就推測findViewById就在這個ButterKnife類的bind方法中進(jìn)行。

3.定義ButterKnife
public class ButterKnife {

    public static void bind(Activity activity){
        Class<?> cls = activity.getClass();
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            BindView bindView = field.getAnnotation(BindView.class);
            if (bindView != null) {
                int ids = bindView.value();
                try {
                    field.set(activity, activity.findViewById(ids));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

我這里就用了反射來操作蹋盆,調(diào)用bind方法后费薄,先用cls.getDeclaredFields();獲取所有的全局變量硝全,然后再對每個變量用field.getAnnotation(BindView.class);來獲取這個變量上面的注解,如果存在的話 int ids = bindView.value(); 來獲取我們傳入的資源楞抡,最后調(diào)用findViewById

field.set(activity, activity.findViewById(ids));

很簡單吧伟众,三個類這樣就能實(shí)現(xiàn)了ButterKnife的效果


image.png

注意判空一定要寫,即使你全部的變量都用了注解召廷,但是如果你DeBug看看凳厢,你會發(fā)現(xiàn),變量中不僅僅只有你定義的竞慢,還存在其他的先紫。

其實(shí)上面都是瞎寫的,ButterKnife的原理根本不是這樣筹煮,雖然我沒看過源碼遮精,但我聽別人說過ButterKnife的實(shí)現(xiàn)并不是這樣的,我這的demo只是仿照了這個功能败潦,具體ButterKnife的原理以后如果有時(shí)間我會單獨(dú)寫本冲。

通過上面的講解就能簡單的實(shí)現(xiàn)注解,我也順便復(fù)習(xí)加總結(jié)了一遍劫扒。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末檬洞,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子沟饥,更是在濱河造成了極大的恐慌添怔,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贤旷,死亡現(xiàn)場離奇詭異澎灸,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)遮晚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拦止,“玉大人县遣,你說我怎么就攤上這事⌒谧澹” “怎么了萧求?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長顶瞒。 經(jīng)常有香客問我夸政,道長,這世上最難降的妖魔是什么榴徐? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任守问,我火速辦了婚禮匀归,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘耗帕。我一直安慰自己穆端,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布仿便。 她就那樣靜靜地躺著体啰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嗽仪。 梳的紋絲不亂的頭發(fā)上荒勇,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天,我揣著相機(jī)與錄音闻坚,去河邊找鬼沽翔。 笑死,一個胖子當(dāng)著我的面吹牛鲤氢,可吹牛的內(nèi)容都是我干的搀擂。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼卷玉,長吁一口氣:“原來是場噩夢啊……” “哼哨颂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起相种,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤威恼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后寝并,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體箫措,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年衬潦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了斤蔓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡镀岛,死狀恐怖弦牡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情漂羊,我是刑警寧澤驾锰,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站走越,受9級特大地震影響椭豫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一赏酥、第九天 我趴在偏房一處隱蔽的房頂上張望喳整。 院中可真熱鬧,春花似錦今缚、人聲如沸算柳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瞬项。三九已至,卻和暖如春何荚,著一層夾襖步出監(jiān)牢的瞬間囱淋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工餐塘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留妥衣,地道東北人。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓戒傻,卻偏偏與公主長得像税手,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子需纳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內(nèi)容