之前有介紹過IOC實現佈局、控件、事件的運行時註解。裏面使用了大量的反射,難免會影響性能。顯而易見,我們常用的butterKnife並沒有使用這種技術,而是使用了APT技術,編譯時完成這些操作,這樣和原始性能相差無幾,不過這樣會增加apk的體積。下面將學習它的實現原理。
一、使用
1、gradle配置
加入以下依賴
// 依賴庫
implementation 'com.jakewharton:butterknife:9.0.0-rc1'
// 註解處理器
annotationProcessor 'com.jakewharton:butterknife-compiler:9.0.0-rc1'
2、綁定
調用如下代碼
ButterKnife.bind(this);
此時編譯一下項目,就會在build編譯目錄下多出來這樣一個文件,截圖如下:
沒錯這就是apt生成的文件。那麼它是如何生成的呢?
二、原理
首先進入bind()方法。跟蹤進入如下代碼:
這裏有兩個地方需要注意:
- 找到當前綁定類的構造方法
- 構造類對象
首先查看這兩個方法具體做了些什麼?
1、findBindingConstructorForClass
注意代碼中通過 cls.getClassLoader().loadClass 加載 APT 生成的類,也就是之前我們在build目錄下看到的那個類。然後拿到它的構造方法。
2、constructor.newInstance
通過分析,通過findBindingConstructorForClass()方法,返回的是APT生成文件的構造器,調用constructor.newInstance()方法,就會實例化該類對象,所以進入該生成類的構造方法。
這裏的 tartget 就是我們自己的 activity。使用target.btn1 就可以訪問類的屬性。所以控件的修飾符不能爲private或static。那麼它是如何找到view的呢?如何設置事件呢?進入方法findRequiredViewAsType()
3、findRequiredViewAsType (找到view)
ok,看到這裏就明白了,還是通過findViewById()來初始化控件。
4、view.setOnClickListener(設置監聽)
值得注意的是這裏的監聽並不是View.OnClickListener。而是它的實現類 DebouncingOnClickListener,代碼如下:
它是一個抽象類,最終調用 onClick() 方法的時候,就會觸發 doClick() 方法回調。交給 target.clickEvent()進行處理。