摘要:上一節(jié)我們已經(jīng)將自動(dòng)生成注解代碼部分介紹完畢,今天這篇文章是自定義注解系列的最后一篇文章。該部分是對(duì)我們前面定義的注解變量與自動(dòng)生成的代碼進(jìn)行綁定,即調(diào)用我們自動(dòng)生成的代碼。
上一節(jié)我們已經(jīng)將自動(dòng)生成注解代碼部分介紹完畢,今天這篇文章是自定義Android注解系列的最后一篇文章。希望大家這一路走來有所收獲。
經(jīng)過前面的了解,我們?nèi)蟛糠郑篵utterknife-annotations、butterknife-compiler與butterknife-bind。現(xiàn)在就剩下最后一部分butterknife-bind。該部分是對(duì)我們前面定義的注解變量與自動(dòng)生成的代碼進(jìn)行綁定,即調(diào)用我們自動(dòng)生成的代碼。
那么我們還是來看下butterknife-bind模板庫(kù)的結(jié)構(gòu):
只有Butterknife一個(gè)類,在這之前我們還需將前面我們已經(jīng)定義好的module引入
dependencies { ... compile project(path: ":butterknife-annotations") }
有了之前的基礎(chǔ),我們Make Project項(xiàng)目工程,之后就可以找到MainActivity$Binding類,或者直接在/app/build/generated/source/kapt/debug/目錄下查找。
BindMainActivity$Binding在構(gòu)造方法中就已經(jīng)調(diào)用了我們的需要的bindView與setOnClickListener方法。所以我們需要使用的話只需實(shí)例化即可。但由于我們是該類是通過注解處理器自動(dòng)生成的,所以我們并不知道它的類名全稱(這里我們相當(dāng)于查看了源碼,才知道是以$Binding結(jié)尾)。這樣我們是不能通過new關(guān)鍵字來實(shí)例化。如此,我們又該如何實(shí)例化它呢?這時(shí)我們?cè)賮砜碽utterknife-bind中的唯一的類Butterknife
public class Butterknife { private Butterknife() { } private staticvoid 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反射來實(shí)例化我們需要的MainActivity$Binding。既然我們已經(jīng)知道自動(dòng)生成的類是由原始類(MainActivity)+后綴($Binding)組成。所以可以很好的使用java反射來實(shí)例化所需的類。對(duì)于外界的調(diào)用只需使用bind方法,傳入需要綁定的類即可。
Use到這里,所以的準(zhǔn)備工作已經(jīng)完成。接下來我們可以開始在MainActivity中使用。首先將定義的庫(kù)進(jìn)行依賴
dependencies { ... implementation project(":butterknife-bind") kapt project(":butterknife-compiler") }
然后在MainActivity中使用
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與默認(rèn)值;使用@OnClick綁定點(diǎn)擊事件;使用Butterknife.bind(this)綁定自定義的注解代碼。這樣我們已經(jīng)完成了與開源庫(kù)Butterknife相似的功能。
progurad現(xiàn)在你在模擬器或者真機(jī)上跑著非常完美,然后你不小心切換到release版本并且開啟了混淆功能。這時(shí)你會(huì)發(fā)現(xiàn)mmp居然沒有效果。為什么呢?debug與release的區(qū)別,絕大數(shù)情況下都是混淆惹的禍。我們?cè)趯?shí)例化自動(dòng)生成的類時(shí)使用的是java反射機(jī)制,所以一旦混淆了我們的java反射就找不到我們指定的類名,這樣自然也就沒有效果了。
那么我們現(xiàn)在又該如何解決呢?別急,是否還記得在系列的Part1我們自定義注解變量中定義了@Keep。
在MainActivity$Binding類上我們使用了@Keep來標(biāo)識(shí)該類,通過該標(biāo)識(shí)告訴proguard不去混淆使用@Keep標(biāo)記的類。要達(dá)到這種效果,我們還需經(jīng)過以下兩個(gè)步驟:
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.為了是依賴庫(kù)的混淆生效,我們還需使用consumerProguardFiles聲明
defaultConfig { ... consumerProguardFiles "proguard-rules.pro" //依賴庫(kù)混淆生效 }
完成這兩步后我們?cè)谥匦聵?gòu)建release版本,這時(shí)程序完美運(yùn)行。終于可以輕松的休息會(huì)了!
End自定義Android注解系列完美收工,希望通過這三部曲能夠幫助大家學(xué)會(huì)如何實(shí)現(xiàn)注解庫(kù)。最后希望大家點(diǎn)贊支持一下,謝謝!
文章中的代碼都可以在Github中獲取到。使用時(shí)請(qǐng)將分支切換到feat_annotation_processing
相關(guān)文章自定義Android注解Part1:注解變量
自定義Android注解Part2:代碼自動(dòng)生成
關(guān)注公眾號(hào):怪談時(shí)間到了
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/71566.html
摘要:下面我們會(huì)自己實(shí)現(xiàn)與注解,實(shí)現(xiàn)中的對(duì)應(yīng)注解功能。帶大家一起來聲明注解變量。知道了它的作用范圍之后,我們?cè)谧远x注解時(shí)就要盡量較小注解的作用范圍,提高項(xiàng)目的編譯與運(yùn)行速度。它們代表自定義的注解能夠作用的對(duì)象。總結(jié)庫(kù)中的自定義注解就完成了。 showImg(https://segmentfault.com/img/bVbc08a?w=740&h=416); 對(duì)于Android注解,或多或少...
閱讀 2022·2021-09-29 09:35
閱讀 1955·2019-08-30 14:15
閱讀 2980·2019-08-30 10:56
閱讀 964·2019-08-29 16:59
閱讀 577·2019-08-29 14:04
閱讀 1310·2019-08-29 12:30
閱讀 1031·2019-08-28 18:19
閱讀 515·2019-08-26 11:51