ButterKnife 原理解讀

轉(zhuǎn)自:小明同學(xué)ButterKnife 原理解讀

最近在研究 Java 中的 Annotation,初衷是先了解注解,然后再了解下 Android 開發(fā)中常用框架的原理。經(jīng)歷的 Android 項(xiàng)目中,使用注解比較多的是:ButterKnife, Roboguice, Dagger 。ButterKnife 主要是 View Binding, 而 Roboguice 和 Dagger 則主要是做 DI(Dependency Injection)。本文主要研究 ButterKnife 的原理。

開始之前,還是應(yīng)該向 ButterKnife 的作者 Jake Wharton 大神以及開源社區(qū)致敬。

ButterKnife 初瞰

ButterKnife 到底是什么?看看官方的解釋:

Bind Android views and callbacks to fields and methods.

通過 ButterKnife 官方文檔,我們可以很快速的使用它。并且可以看到 ButterKnife 主要是實(shí)例化 View 或者給某個(gè) View 添加各種事件 Listenters。

image

所以使用 ButterKnife 主要有幾步:

1.Gradle 中引入 ButterKnife 框架:

compile 'com.jakewharton:butterknife:8.0.1'

2.ButterKnife 初始化:

@Override
protected void onCreate(Bundle savedInstanceState) {          
    super.onCreate(savedInstanceState);   
    setContentView(getLayoutResourceId());    
    ButterKnife.bind(this);
}}

3.聲明 Field/Method

@Bind(R.id.btn_home)ImageView homeBtn;
@Bind(R.id.btn_explore)ImageView exploreBtn;
@OnClick(R.id.btn_home) void clickHomeBtn() {      
    // Handle the home btn click
}

Java Annotation

如果你對(duì)注解了解比較少,在進(jìn)一步了解 ButterKnife 之前,有必要了解一下 Java Annotation 的基礎(chǔ)知識(shí)??梢詤⒖既缦聝煞葙Y料:

  1. Mkyong Java Custom Annotations

  2. Trenia Java Annotations

通過上面的例子以及講解,我們可以知道如何自定義注解。自定義注解我們需要知道兩個(gè)基礎(chǔ)的元注解@Retention@Target.

元注解 @Retention

@Retention 保留時(shí)間:有三類值可以選擇,SOURCE RUNTIME CLASS。

SOURCE 源碼時(shí)保留:使用此類的注解多為標(biāo)記注解,比如 @Override、@Deprecated、@SuppressWarnings 等。

RUNTIME 運(yùn)行時(shí)保留:程序在運(yùn)行過程中,使用這些 Annotation, 比如我們常用的 @Test

CLASS 編譯時(shí)保留:Java 文件在編譯時(shí)由 apt 自動(dòng)解析,需要自定義類繼承自 AbstractProcessor 并重寫 Process 函數(shù)。比如 ButterKnife 中使用的 @BindView, @OnClick 等就是聲明為 CLASS 的。

元注解 @Target

Target 表示注解可以用來修飾哪些元素??蛇x值包括 TYPE, METHOD, CONSTRUCTOR, FIELD, PARAMETER 等。

ButterKnifeProcessor

ButterKnife 中所有的注解都使用 Retention 為 CLASS 保留。所以在 ButterKnife 中,有個(gè)很重要的 ButterKnifeProcessor。當(dāng) java 文件進(jìn)行編譯時(shí),ButterKnifeProcessor 的 process() 方法被調(diào)用,生成相關(guān)的 ViewBinder 類,用于將 View 或者 Listener 進(jìn)行綁定。

ButterKnifeProcessor 的關(guān)鍵邏輯如下:

image

process() 會(huì)找到所有 ButterKnife 相關(guān)的 annotation,并將這些相應(yīng)的注解生成為 ViewBinder 類,一個(gè) ViewBinder 示例如下:

image

ViewBinder 通過 findViewById 實(shí)例化 Activity 中頁面上的組件,并且能夠設(shè)置各控件的點(diǎn)擊時(shí)間,滑動(dòng)事件等。

為什么 ButterKnife Annotation 的字段或者方法不能聲明為 private?

bind() 方法中,通過 activity.homeBtn 對(duì) View 賦值。因此所有 ButterKnife annotation 標(biāo)記的 field 或者 method 都不能聲明為 private, 因?yàn)?private 沒辦法在 ViewBinder 中直接訪問。由此可見:

ButterKnife 并不是依靠反射實(shí)現(xiàn) View Injection 的!

ButterKnife.bind(this)

在 ButterKnife 工作之前,我們一定得在設(shè)置 View 后調(diào)用 ButterKnife.bind(Activity) ,這樣才能使 ButterKnife View 注入成功。那么 ButterKnife.bind(Activity) 是如何工作的呢?

image

App 在打包時(shí),ButterKnife Processor 就為所有使用 ButterKnife 注解的 Activity 生成 ViewBinder()。通過上述代碼可以看到,ButterKnife 會(huì)嘗試實(shí)例化當(dāng)前 Activity 所關(guān)聯(lián)的所有 ViewBinder 類。實(shí)例化之后再調(diào)用 ViewBinder.bind(...) 方法,bind() 方法是在 App 運(yùn)行過程中才會(huì)被調(diào)用的。于是當(dāng)前 Avtivity 的 View 被實(shí)例化賦值,如果有點(diǎn)擊事件的注解,也會(huì)綁定相應(yīng)的事件。

結(jié)語

ButterKnife 主要是做 View 注入的,使用起來比較簡(jiǎn)便。當(dāng)然如果你想做一些 依賴注入,比如 Android MVP 架構(gòu)中 Activity 與 Presenter 的依賴。你可能需要借助一些其他的庫(kù), 比如 Dagger。研究下 ButterKnife 的原理,才發(fā)現(xiàn)這個(gè)庫(kù)做得如此的睿智。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 最近在研究 Java 中的 Annotation,初衷是先了解注解,然后再了解下 Android 開發(fā)中常用框架的...
    小明同學(xué)閱讀 5,981評(píng)論 1 11
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,881評(píng)論 25 709
  • 俗話說的好“不想偷懶的程序員,不是好程序員”,我們?cè)谌粘i_發(fā)android的過程中,在前端activity或者fr...
    蛋西閱讀 5,067評(píng)論 0 14
  • 看到這個(gè),心中突然涌起一陣無法壓抑 我以最快的速度找到五月天 那些我堅(jiān)持的堅(jiān)持 那些鋒利那些模糊那些歌曲 一種呼吸...
    逆風(fēng)有楊閱讀 358評(píng)論 0 2
  • 早上還在床上就看到班導(dǎo)在群里發(fā)的信息,說上午一二節(jié)上課,今天開始上課。因?yàn)槭桥R時(shí)通知的,結(jié)果課還是沒上成,...
    天空藍(lán)上閱讀 104評(píng)論 0 0

友情鏈接更多精彩內(nèi)容