自定義Android註解Part3:綁定

clipboard.png

上一節咱們已經將自動生成註解代碼部分介紹完畢,今天這篇文章是自定義Android註解系列的最後一篇文章。但願你們這一路走來有所收穫。java

通過前面的瞭解,咱們三大部分:butterknife-annotations、butterknife-compiler與butterknife-bind。如今就剩下最後一部分butterknife-bind。該部分是對咱們前面定義的註解變量與自動生成的代碼進行綁定,即調用咱們自動生成的代碼。android

那麼咱們仍是來看下butterknife-bind模板庫的結構:git

clipboard.png

只有Butterknife一個類,在這以前咱們還需將前面咱們已經定義好的module引入github

dependencies {
    ...
    compile project(path: ':butterknife-annotations')
}

有了以前的基礎,咱們Make Project項目工程,以後就能夠找到MainActivity$Binding類,或者直接在/app/build/generated/source/kapt/debug/目錄下查找。segmentfault

Bind

MainActivity$Binding在構造方法中就已經調用了咱們的須要的bindView與setOnClickListener方法。因此咱們須要使用的話只需實例化便可。但因爲咱們是該類是經過註解處理器自動生成的,因此咱們並不知道它的類名全稱(這裏咱們至關於查看了源碼,才知道是以$Binding結尾)。這樣咱們是不能經過new關鍵字來實例化。如此,咱們又該如何實例化它呢?這時咱們再來看butterknife-bind中的惟一的類Butterknifeapi

public class Butterknife {
 
    private Butterknife() {
 
    }
 
    private static <T extends Activity> void initialization(T target, String suffix) {
        Class<?> tClass = target.getClass();
        String className = tClass.getName();
        try {
            Class<?> bindingClass = tClass.getClassLoader().loadClass(className + suffix);
            Constructor<?> constructor = bindingClass.getConstructor(tClass);
            constructor.newInstance(target);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
 
    public static void bind(Activity activity) {
        initialization(activity, ConstantUtils.BINDING_BUTTERKNIFE_SUFFIX);
    }
}

在initialization方法中,咱們經過java反射來實例化咱們須要的MainActivity$Binding。既然咱們已經知道自動生成的類是由原始類(MainActivity)+後綴($Binding)組成。因此能夠很好的使用java反射來實例化所需的類。對於外界的調用只需使用bind方法,傳入須要綁定的類便可。app

Use

到這裏,因此的準備工做已經完成。接下來咱們能夠開始在MainActivity中使用。首先將定義的庫進行依賴ide

dependencies {
    ...
    implementation project(':butterknife-bind')
    kapt project(':butterknife-compiler')
}

而後在MainActivity中使用ui

class MainActivity : AppCompatActivity() {
 
    @BindView(R.id.public_service, R.string.public_service)
    lateinit var sName: TextView
 
    @BindView(R.id.personal_wx, R.string.personal_wx)
    lateinit var sPhone: TextView
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Butterknife.bind(this)
    }
 
    @OnClick(R.id.public_service)
    fun nameClick(view: View) {
        Toast.makeText(this, getString(R.string.public_service_click_toast), Toast.LENGTH_LONG).show()
    }
 
    @OnClick(R.id.personal_wx)
    fun phoneClick(view: View) {
        Toast.makeText(this, getString(R.string.personal_wx_click_toast), Toast.LENGTH_LONG).show()
    }
}

咱們使用@BindView綁定View的Id與默認值;使用@OnClick綁定點擊事件;使用Butterknife.bind(this)綁定自定義的註解代碼。這樣咱們已經完成了與開源庫Butterknife類似的功能。this

progurad

如今你在模擬器或者真機上跑着很是完美,而後你不當心切換到release版本而且開啓了混淆功能。這時你會發現mmp竟然沒有效果。爲何呢?debug與release的區別,絕大數狀況下都是混淆惹的禍。咱們在實例化自動生成的類時使用的是java反射機制,因此一旦混淆了咱們的java反射就找不到咱們指定的類名,這樣天然也就沒有效果了。

那麼咱們如今又該如何解決呢?別急,是否還記得在系列的Part1咱們自定義註解變量中定義了@Keep

在MainActivity$Binding類上咱們使用了@Keep來標識該類,經過該標識告訴proguard不去混淆使用@Keep標記的類。要達到這種效果,咱們還需通過如下兩個步驟:

1.在butterknife-bind的proguard-rules.pro文件中添加以下代碼

-keep class com.idisfkj.butterknife.annotations.Keep**
-keep @com.idisfkj.butterknife.annotations.Keep public class *
-keepclassmembers @com.idisfkj.butterknife.annotations.Keep class ** {*;}

2.爲了是依賴庫的混淆生效,咱們還需使用consumerProguardFiles聲明

defaultConfig {
        ...
        consumerProguardFiles 'proguard-rules.pro' //依賴庫混淆生效
    }

完成這兩步後咱們在從新構建release版本,這時程序完美運行。終於能夠輕鬆的休息會了!

End

自定義Android註解系列完美收工,但願經過這三部曲可以幫助你們學會如何實現註解庫。最後但願你們點贊支持一下,謝謝!

文章中的代碼均可以在Github中獲取到。使用時請將分支切換到feat_annotation_processing

相關文章

自定義Android註解Part1:註解變量

自定義Android註解Part2:代碼自動生成

關注

公衆號:怪談時間到了

clipboard.png

相關文章
相關標籤/搜索