最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

自定義Android注解系列教程之注解變量

 更新時(shí)間:2018年07月06日 15:09:28   作者:idisfkj  
這篇文章主要給大家介紹了關(guān)于自定義Android注解系列教程之注解變量的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

對(duì)于Android注解,或多或少都有一點(diǎn)接觸,但相信大多數(shù)人都是在使用其它依賴庫的時(shí)候接觸的。因?yàn)橛行烊绻阆胧褂盟捅仨毷褂盟峁┑淖⒔?。例如:ButterKnife、Dagger2、Room等等。

至于為何使用注解?使用過的應(yīng)該都知道,最明顯的就是方便、簡潔。通過使用注解可以在項(xiàng)目編譯階段,幫助我們自動(dòng)生成一些重復(fù)的代碼,減輕我們的負(fù)擔(dān)。典型的ButterKnife本質(zhì)就是使用Android注解,通過注解來減少我們對(duì)view.findViewById的編寫,提高我們的開發(fā)效率。上一個(gè)系列(AAC)的Room也是一樣,我們可以簡單的回顧一下:

@Entity(tableName = "contacts")
data class ContactsModel(
 @PrimaryKey
 @ColumnInfo(name = "contacts_id")
 val id: Int,
 @ColumnInfo(name = "name")
 val name: String,
 @ColumnInfo(name = "phone")
 val phone: String
)

通過使用注解來定義一個(gè)實(shí)體表,也就10行左右的代碼。如果要我們?nèi)孔约簩懩墙^對(duì)要兩三百行代碼了,而且其中還可能出錯(cuò),又要改bug等等。效率就嚴(yán)重降低。對(duì)于依賴庫如果都這么麻煩也就不會(huì)有人用了。

那么如何判斷一個(gè)依賴庫是否需要使用注解呢?其實(shí)很簡單,只要記住以下兩點(diǎn)即可:

  • 需要生成的代碼不能與項(xiàng)目邏輯有關(guān)
  • Android注解只能生成代碼,并不能修改代碼

這里透露一下,Android注解的本質(zhì)是使用Java的反射機(jī)制,后續(xù)會(huì)詳細(xì)說明

項(xiàng)目架構(gòu)

相信ButterKnife應(yīng)該有接觸過吧,沒有的也沒關(guān)系,現(xiàn)在正是時(shí)候。下面我們會(huì)自己實(shí)現(xiàn)BindView與OnClick注解,實(shí)現(xiàn)ButterKnife中的對(duì)應(yīng)注解功能。那么我先來看下整體的項(xiàng)目架構(gòu)

通過項(xiàng)目圖,我們可以清晰的看到,主要分為三個(gè)部分

  • butterknife-annotations:注解庫,包含BindView與OnClick等自定義的注解
  • butterknife-bind:綁定庫,自定義的注解與聲明的類綁定
  • butterknife-compiler: 解析編譯生成庫,解析聲明類中的注解,在編譯時(shí)自動(dòng)生成相應(yīng)的代碼。

為了幫助大家能夠更輕松的理解Android注解,今天主要分析的就是butterknife-annotations這個(gè)注解庫。帶大家一起來聲明注解變量。

BindView

為了要實(shí)現(xiàn)開源庫butterknife類似的綁定id效果,這里我們先定義一個(gè)BindView注解,具體如下:

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.FIELD)
public @interface BindView {
 @IdRes int[] value();
}

嗯,還是很簡單的對(duì)吧。也就5行代碼解決BindView注解的定義。

那么再來詳細(xì)剖析這5行代碼。

Retention

首先是第一行代碼的Retention,看它的使用方式就能知道,它也是一個(gè)聲明了的注解。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
 /**
 * Returns the retention policy.
 * @return the retention policy
 */
 RetentionPolicy value();
}

通過源碼我們可以看出該注解只接收一個(gè)參數(shù),該參數(shù)為RetentionPolicy類型。那么我們?cè)谶M(jìn)一步深入RetentionPolicy:

public enum RetentionPolicy {
 /**
 * Annotations are to be discarded by the compiler.
 */
 SOURCE,
 
 /**
 * Annotations are to be recorded in the class file by the compiler
 * but need not be retained by the VM at run time. This is the default
 * behavior.
 */
 CLASS,
 
 /**
 * Annotations are to be recorded in the class file by the compiler and
 * retained by the VM at run time, so they may be read reflectively.
 *
 * @see java.lang.reflect.AnnotatedElement
 */
 RUNTIME
}

在這里我們發(fā)現(xiàn)它其實(shí)是一個(gè)枚舉,在枚舉中支持三個(gè)常量,分別為SOURCE、CLASS與RUNTIME。它們的區(qū)別主要是作用的周期范圍,下面我再對(duì)這三個(gè)的作用進(jìn)行翻譯一遍:

  • SOURCE: 使用該標(biāo)明的注解將在編譯階段就被拋棄掉。
  • CLASS:使用該標(biāo)明的注解將在編譯階段記錄到生成的class文件中,但在運(yùn)行階段時(shí)又會(huì)被VM拋棄。默認(rèn)是該模式。
  • RUNTIME:使用該標(biāo)明的注解將在編譯階段被保存在生成的class文件中,同時(shí)在運(yùn)行階段時(shí)會(huì)保存到VM中。所以它該注解將一直存在,自然能夠通過java的反射機(jī)制進(jìn)行讀取。

所以它們的存在的生命時(shí)長為SOURCE < CLASS < RUNTIME。知道了它的作用范圍之后,我們?cè)谧远x注解時(shí)就要盡量較小注解的作用范圍,提高項(xiàng)目的編譯與運(yùn)行速度。

因?yàn)槲覀兊腂indView注解只是為了進(jìn)行Viwe的綁定,所以在編譯之后就無需存在,所以這里就使用了CLASS來進(jìn)行標(biāo)明。

Target

下面我們?cè)趤砜吹诙写a,這里使用到了另一個(gè)注解Target,我們還是來看下它的源碼:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
 /**
 * Returns an array of the kinds of elements an annotation type
 * can be applied to.
 * @return an array of the kinds of elements an annotation type
 * can be applied to
 */
 ElementType[] value();
}

可以看到注解的源碼都非常簡單,這里接收了一個(gè)ElementType數(shù)組參數(shù),ElementType不難猜出它的類型也是一個(gè)枚舉:

public enum ElementType {
 /** Class, interface (including annotation type), or enum declaration */
 TYPE,
 
 /** Field declaration (includes enum constants) */
 FIELD,
 
 /** Method declaration */
 METHOD,
 
 /** Formal parameter declaration */
 PARAMETER,
 
 /** Constructor declaration */
 CONSTRUCTOR,
 
 /** Local variable declaration */
 LOCAL_VARIABLE,
 
 /** Annotation type declaration */
 ANNOTATION_TYPE,
 
 /** Package declaration */
 PACKAGE,
 
 /**
 * Type parameter declaration
 *
 * @since 1.8
 */
 TYPE_PARAMETER,
 
 /**
 * Use of a type
 *
 * @since 1.8
 */
 TYPE_USE
}

ElementType中雖然有10常量,但我們實(shí)際真正常用的也就是前面8種。它們代表自定義的注解能夠作用的對(duì)象。分別為:

  • TYPE: 作用于類、接口或者枚舉
  • FIELD:作用于類中聲明的字段或者枚舉中的常量
  • METHOD:作用于方法的聲明語句中
  • PARAMETER:作用于參數(shù)聲明語句中
  • CONSTRUCTOR:作用于構(gòu)造函數(shù)的聲明語句中
  • LOCAL_VARIABLE:作用于局部變量的聲明語句中
  • ANNOTATION_TYPE:作用于注解的聲明語句中
  • PACKAGE:作用于包的聲明語句中
  • TYPE_PARAMETER:java 1.8之后,作用于類型聲明的語句中
  • TYPE_USE:java 1.8之后,作用于使用類型的任意語句中

結(jié)合我們的BindView的作用是對(duì)View進(jìn)行id綁定,自然是作用與聲明的字段上。所以在BindView中使用了FIELD。

再來看第四行代碼

@IdRes int[] value()

有了上面的注解接觸,不難理解這是標(biāo)明BindView將接收一個(gè)int類型的數(shù)組參數(shù)。對(duì)于開源庫butterknife中的BindView是接收需要綁定的View的id,這里我們做一個(gè)改版,再接收一個(gè)String的id,用來為綁定的View設(shè)置默認(rèn)值。這樣我們自定義了的BindView注釋就完成了。

OnClick

下面我們?cè)僮远x一個(gè)OnClick點(diǎn)擊的注解,經(jīng)過上面的分析,可以在腦海中想想Retention與Target分別什么值?

想好了之后我們?cè)趤磉^一遍

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface OnClick {
 @IdRes int value();
}

Retention的作用范圍與BindView一樣首頁SOURCE,在編譯之后就無需存在;Target的作用對(duì)象與BindView不同,既然是點(diǎn)擊事件的點(diǎn)擊操作,自然是作用在操作邏輯的方法上,所以這里使用METHOD。

keep

文章開頭有提及到本質(zhì)是通過注解來自動(dòng)生成代碼,為我們創(chuàng)建所需的類,那么在實(shí)際開發(fā)中一旦我們的項(xiàng)目混淆了,這將會(huì)導(dǎo)致自動(dòng)創(chuàng)建的類失效,從而導(dǎo)致我們自定義的注解失效。所以為了防止其失效,我們?cè)谶@里再定義一個(gè)注解keep:

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface Keep {
}

Retention的作用范圍是在class文件中還要能夠被其它c(diǎn)lass調(diào)用,所以這里使用CLASS;Target作用對(duì)象是自動(dòng)生成的類,所以使用TYPE。至于參數(shù)則不必要,它只是為了標(biāo)明類,防止其被混淆。

總結(jié)

butterknife-annotations庫中的自定義注解就完成了。通過上面的分析,我們注意點(diǎn)主要?dú)w結(jié)于以下三點(diǎn):

  • Retention: 明確注解作用的生命時(shí)長,盡早的消除
  • Target: 明確注解作用的對(duì)象
  • Keep: 防止后續(xù)自動(dòng)生成的類被混淆

注解變量的定義就到這結(jié)束了,同時(shí)文章中的代碼都可以在Github (本地下載)中獲取到。使用時(shí)請(qǐng)將分支切換到feat_annotation_processing

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • 詳解Gradle依賴沖突解決方式

    詳解Gradle依賴沖突解決方式

    這篇文章主要介紹了Gradle依賴沖突解決方式,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • 詳解Android 進(jìn)程間通信的幾種實(shí)現(xiàn)方式

    詳解Android 進(jìn)程間通信的幾種實(shí)現(xiàn)方式

    在Android SDK中提供了4種用于跨進(jìn)程通訊的方式。這篇文章主要介紹了詳解Android 進(jìn)程間通信的幾種實(shí)現(xiàn)方式,有興趣的可以了解一下。
    2017-01-01
  • ViewPager判斷是向左劃還是右劃的實(shí)例

    ViewPager判斷是向左劃還是右劃的實(shí)例

    下面小編就為大家?guī)硪黄猇iewPager判斷是向左劃還是右劃的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-04-04
  • Android實(shí)現(xiàn)左滑退出Activity的完美封裝

    Android實(shí)現(xiàn)左滑退出Activity的完美封裝

    這篇文章主要介紹了Android實(shí)現(xiàn)左滑退出Activity的完美封裝,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Angular5.0.0新特性

    Angular5.0.0新特性

    Angular5.0.0是一款非常優(yōu)秀的前端JS框架,已經(jīng)被用于google多款產(chǎn)品當(dāng)中,這篇文章主要介紹了Angular5.0.0新特性,需要的朋友可以參考下
    2017-11-11
  • Android使用AutoCompleteTextView實(shí)現(xiàn)自動(dòng)填充功能的案例

    Android使用AutoCompleteTextView實(shí)現(xiàn)自動(dòng)填充功能的案例

    今天小編就為大家分享一篇關(guān)于Android使用AutoCompleteTextView實(shí)現(xiàn)自動(dòng)填充功能的案例,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • Android內(nèi)置的OkHttp用法介紹

    Android內(nèi)置的OkHttp用法介紹

    okhttp是一個(gè)第三方類庫,用于android中請(qǐng)求網(wǎng)絡(luò)。這是一個(gè)開源項(xiàng)目,是安卓端最火熱的輕量級(jí)框架,由移動(dòng)支付Square公司貢獻(xiàn)(該公司還貢獻(xiàn)了Picasso和LeakCanary) 。用于替代HttpUrlConnection和Apache HttpClient
    2022-08-08
  • Android利用Paint自定義View實(shí)現(xiàn)進(jìn)度條控件方法示例

    Android利用Paint自定義View實(shí)現(xiàn)進(jìn)度條控件方法示例

    這篇文章主要給大家介紹了關(guān)于Android利用Paint自定義View實(shí)現(xiàn)進(jìn)度條控件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11
  • Android實(shí)現(xiàn)畫中畫功能(圖片)

    Android實(shí)現(xiàn)畫中畫功能(圖片)

    畫中畫是一種特殊類型的多窗口模式,最常用于視頻播放。這篇文章主要介紹了Android實(shí)現(xiàn)畫中畫功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 超酷炫的Android碎紙機(jī)效果推薦

    超酷炫的Android碎紙機(jī)效果推薦

    這篇文章運(yùn)用xml和java實(shí)現(xiàn)了Android版的碎紙機(jī)動(dòng)畫,效果非常好,推薦給有需要的小伙伴們使用。
    2016-07-07

最新評(píng)論

修文县| 开鲁县| 都兰县| 会理县| 偃师市| 嘉峪关市| 青铜峡市| 西吉县| 江华| 宜兰市| 子洲县| 石泉县| 随州市| 南岸区| 县级市| 邵阳县| 柘城县| 罗源县| 屯门区| 汽车| 江华| 乐清市| 漳浦县| 桐乡市| 区。| 平果县| 大足县| 太湖县| 江源县| 崇左市| 城步| 右玉县| 浦江县| 东丽区| 正阳县| 五寨县| 宁陵县| 佛坪县| 宁乡县| 积石山| 建始县|