【Android】ButterKnife 簡單原理實現

來源:互聯網
上載者:User

標籤:

ButterKnifeProcedure

ButterKnife的原理簡述

範例程式碼ButterKnifeProcedure

Pluggable Annotation Processing

註解處理器
Java5 中叫APT(Annotation Processing Tool),在Java6開始,正常化為 Pluggable Annotation Processing。

第一步(收集資訊)

找到所有被註解的屬性或者方法,將所有的資訊收集到對應的“類資料集”中。

第二步(產生源檔案)

根據每一個“類資料集”,產生對應的java源檔案。由於這些檔案並不是在運行時產生的,因此也無需動態編譯,註解處理器運行完成之後,
編譯器會處理所有的編譯流程。

第三步(動態注入)

運行時動態注入,即使用者常規調用的 ButterKnife.bind(activity)

這一步為了避免蹩腳的調用,使用了運行時反射,但是作者對每一個類進行了緩衝,因此,不會對執行效率產生多大影響。

在最新的 ButterKnife 源碼(2015.06.08)中,ButterKnife已經重構了部分方法:

ButterKnife#inject -> ButterKnife#bind

@InjectView -> @FindView

等等,具體變化可以去看官方文檔,**本文檔後續代碼使用最新版本代碼示範**。

極簡實現示範 示範代碼說明
  1. 範例程式碼由 ButterKnife 簡化而來,部分定義和實現有刪改,只能綁定 Activity 中的 View 欄位
  2. 為了避免引入Android平台,但是又需要更直觀,所以mock了android的兩個類,Activity 和 View
  3. 為了避免使用 Pluggable Annotation Processing 過程中的jar包要求,以及波及不必要的java檔案,請使用命令列運行示範,直接運行 ./run.sh 即可查看結果
  4. 保證 CLASSPATH 中含有tools.jar
第一步(收集資訊)
  1. 在每一個類中找到所有被 FindView 註解的欄位
  2. 每一個需要綁定的欄位資訊都儲存為一個 FieldViewBinding 對象,比如:

    @FindView(100)View vView1;得到:new FieldViewBinding(vView1, android.view.View, 100)
  3. 將欄位分類,擷取每一個類的“類資料集”BindingClass,比如, MainActivity 對應的 “類資料集” 如下:

    MainActivity:    List<FieldViewBinding> fieldViewBindings = new ArrayList<FieldViewBinding>();    fieldViewBindings.add(new FieldViewBinding(vView1, android.view.View, 100))    fieldViewBindings.add(new FieldViewBinding(vView2, android.view.View, 200))
第二步(產生 Bind 工具類源檔案)

為了便於在反射時容易執行個體化產生的類,每一個產生的類都實現了一個 ActivityBinder 介面,因此,根據 MainActivity “類資料集”產生的檔案如下:

package sample;import android.view.View;import android.app.Activity;import butterknife.ButterKnife.ActivityBinder;public class MainActivity$$ViewBinder implements ActivityBinder<sample.MainActivity> {    @Override    public void bind(sample.MainActivity target) {        View view;        view = target.findViewById(100);        target.vView1 = view; //這裡要求 vView1 的存取權限為 package 層級        view = target.findViewById(200);        target.vView2 = view;    }}
第三步(動態注入)

我們在 MainActivity 中調用 ButterKnife#bind,第一件事就是找到對應產生的 Bind 工具類,這裡遵循命名規則(在對應類後增加 $$ViewBinder 尾碼),直接使用動態載入並執行個體化:

Class<?> activityBindingClass = Class.forName(targetClass.getName() + ButterKnifeProcessor.SUFFIX);activityBinder = (ActivityBinder) activityBindingClass.newInstance();

獲得相應的 ActivityBinder 之後,使用 ActivityBinder#bind 進行綁定,與手動調用 findViewById 效果相同

運行

運行:

ButterKnifeProcedure/src$ ./run.sh

結果:

mainActivity.vView1.id = 100mainActivity.vView2.id = 200
Android分享 Q群:315658668

【Android】ButterKnife 簡單原理實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.