Android AOP基本用法全面詳解
什么是AOP
AOP(Aspect Oriented Programming)意為面向切面編程,指通過預(yù)編譯方式和運(yùn)行期間動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)。
其廣泛的應(yīng)用在代碼的后期修改與維護(hù)之中,它對(duì)原代碼侵入性少,容易擴(kuò)展輔助功能,可以使原執(zhí)行邏輯與改變執(zhí)行邏輯解耦。
現(xiàn)在有一個(gè)智能門,以前的開門的邏輯是:輸入密碼 -> 拎動(dòng)把手 -> 開門,現(xiàn)在呢業(yè)主覺得密碼有可能被盜,不夠安全,希望加上指紋驗(yàn)證。這時(shí)候我們只需要將 驗(yàn)證指紋 這一步插入到 開門 之前就完成了,現(xiàn)在的邏輯是:輸入密碼 -> 拎動(dòng)把手 -> 指紋驗(yàn)證 -> 開門。這種思維就是一種面向切面的思維。
什么是AspectJ
要知道AOP只是一種編程思想,那么,在android中,我們?cè)撏ㄟ^何種工具來實(shí)現(xiàn)這種思想呢,沒錯(cuò),就是AspectJ。要掌握AspectJ首先要明確下面的幾大概念:
Advice(通知):定義需要被注入到.class字節(jié)碼文件中的代碼,通俗點(diǎn)兒來說就是告訴編織器哪里是你需要插入的代碼。
- @Pointcut :定義切點(diǎn)、標(biāo)記方法以便于重用。
- @Before :前置通知,其內(nèi)容在切點(diǎn)之前執(zhí)行。
- @Around :環(huán)繞通知,其內(nèi)容貫穿整個(gè)切點(diǎn)前后。
- @After:后置通知,其內(nèi)容在切點(diǎn)之后執(zhí)行。
- @AfterReturning:返回通知,其內(nèi)容在切點(diǎn)返回結(jié)果后再執(zhí)行。
- @AfterThrowing:異常通知,其內(nèi)容在切點(diǎn)拋出異常時(shí)執(zhí)行。
JoinPoint(連接點(diǎn)):即允許你插入代碼的地方。
Pointcut(切入點(diǎn)):是對(duì)連接點(diǎn)的篩選與定義的一種表達(dá)式。
- 如下圖所示,"execution(* android.view.View.OnClickListener.onClick(..))"是一個(gè)完整的切點(diǎn)表達(dá)式,它是由execution(<修飾符模式>? <返回類型模式> <方法名模式>(<參數(shù)模式>) <異常模式>?)組成的,其中<修飾符模式>和<異常模式>可以省略。
Aspect(切面):切面是通知和切入點(diǎn)的結(jié)合。
Weaving(織入):這個(gè)很好理解就是把我們定義好的切面注入到目標(biāo)對(duì)象中去的過程。
基本用法
插件配置
//在根build.gradle下配置: dependencies { ... classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.8' } //在app/build.gradle下配置 apply plugin: 'com.hujiang.android-aspectjx' aspectjx { //關(guān)閉AspectJX功能 enabled true //織入遍歷符合條件的庫 //includeJarFilter 'universal-image-loader', 'AspectJX-Demo/library' //排除包含‘universal-image-loader'的庫 //excludeJarFilter 'universal-image-loader' }
定義切面
創(chuàng)建一個(gè)類,并通過@Aspect定義為一個(gè)切面。
@Aspect public class AspectTest { ...... }
創(chuàng)建通知、添加切點(diǎn)表達(dá)式
在該類中添加需要編織的方法,并通過通知和切點(diǎn)表達(dá)式來定義它。Ok,一個(gè)簡單的防抖的OnClick判斷就切入到你的程序中去了。相信其他業(yè)務(wù)你也能很好的利用AspectJ來處理了。
@Aspect public class AspectTest { private static final String TAG = "AspectTest"; @Around("execution(* android.view.View.OnClickListener.onClick(..))") public void onClickListener(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ Log.d(TAG, "onClick"); if (!NoDoubleClickUtils.isDoubleClick()){ proceedingJoinPoint.proceed(); //切回到切點(diǎn)并執(zhí)行后續(xù)代碼 } } }
補(bǔ)充:第三方庫兼容
有時(shí)候我們?cè)谑褂肁spectJ的時(shí)候可能會(huì)遇到引入了一些其他的三方庫的情況,而我們又需要對(duì)其內(nèi)的連接點(diǎn)進(jìn)行編織、切入。如上述點(diǎn)擊事件防抖的例子,可能用到了Butterknife來注解@onClick(),這時(shí)你會(huì)發(fā)現(xiàn)上述切入表達(dá)式不起作用了,為什么呢,我們看一下Butterknife中的@OnClick定義就知道了。
@Target(METHOD) @Retention(RUNTIME) @ListenerClass( targetType = "android.view.View", setter = "setOnClickListener", type = "butterknife.internal.DebouncingOnClickListener", method = @ListenerMethod( name = "doClick", parameters = "android.view.View" ) ) public @interface OnClick { /** View IDs to which the method will be bound. */ @IdRes int[] value() default { View.NO_ID }; }
我們可以發(fā)現(xiàn)。其通過Annotation Processor對(duì)@OnClick進(jìn)行掃描,并將android.view.View.OnClickListener.onClick方法替換為butterknife.internal.DebouncingOnClickListener.doClick方法。因此為了兼容ButterKnife上述切入點(diǎn)表達(dá)式應(yīng)該改為如下方式,及對(duì)butterknife的OnClick方法進(jìn)行切入。
@Around("execution(* android.view.View.OnClickListener.onClick(..)) || execution(@butterknife.OnClick * *(..))") public void onClickListener(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ Log.d(TAG, "onClick"); if (!NoDoubleClickUtils.isDoubleClick()){ proceedingJoinPoint.proceed(); } }
以上就是Android AOP基本用法全面詳解的詳細(xì)內(nèi)容,更多關(guān)于Android AOP基本用法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
android BitmapFactory.Options使用方法詳解
這篇文章主要為大家詳細(xì)介紹了android BitmapFactory.Options使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01Android實(shí)現(xiàn)實(shí)時(shí)滑動(dòng)ViewPager的2種方式
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)實(shí)時(shí)滑動(dòng)ViewPager的2種方式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10Android中替換WebView加載網(wǎng)頁失敗時(shí)的頁面
這篇文章主要介紹了Android中替換WebView加載網(wǎng)頁失敗時(shí)的頁面,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-01-01在啟動(dòng)欄制作android studio啟動(dòng)圖標(biāo)
這篇文章主要介紹了在啟動(dòng)欄制作android studio啟動(dòng)圖標(biāo)的相關(guān)知識(shí),需要的朋友可以參考下2018-03-03

Android Studio實(shí)現(xiàn)補(bǔ)間動(dòng)畫

android 9.0 launcher3 去掉抽屜式顯示所有 app(代碼詳解)