面向切面編程(AOP)在Android中的應用

看完本篇文章你將學到什麼?

1.基本瞭解AOP的編程思想,以及如何在Android中使用AOP的思想  
2.藉助AspectJ用AOP的思想實現埋點邏輯  
3.藉助AspectJ用AOP的思想實現屏蔽快速點擊事件的處理

什麼是AOP

AOP,字面翻譯爲面向切面編程。它是一種編程思想,不是什麼新技術。可以這麼理解,在Android開發過程中,我們經常會在我們的具體業務代碼中加入全局性、系統性的與具體業務無關的代碼。比如埋點、動態申請權限等等。AOP的思想就是將這些與業務無關的系統性的功能解耦出來,讓代碼看起來更清晰一點。使用AOP思想與正常程序流程的對比我們可以通過下面示例圖片有個基礎的認識:

上圖1我們看到是我們正常的程序流程,程序的執行就像水從管道流出一樣從上到下順暢的縱向執行。圖2爲我們展示了AOP思想的程序執行流程,從圖中可以看到我們的管道被從某一點橫向的切開(AOP中將這個切點定義爲pointCut),然後會在切入點植入一段我們在Aspect(類似於Java的類的理念,AOP中用來管理切點和執行代碼塊的一個概念)中定義的代碼。示例僅是一種演示,實際情況是植入執行的代碼塊可以向被插入方法的前後同時植入代碼塊。目前實現AOP思想的框架有AspectJ、Spring、JBoss4.0等等。

AspectJ框架

爲什麼這裏選擇介紹AspectJ呢?主要是我公司的項目使用的是這個框架。那麼什麼是AspectJ?

它是實現AOP思想的一個框架,擁有自己的編譯器和語法,可以在編譯期間將需要植入的代碼編譯成Java代碼插入到你的源代碼文件當中。更直白點

我們的Android項目引用也非常的簡單,2步就可以搞定:

  • 在項目的根目錄的Build.gradle文件中加入下面的代碼:

    1dependencies {
    2    classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.0'
    3}
    
  • 在你的app模塊或者其他module中添加依賴:

    1dependencies {
    2   implementation 'org.aspectj:aspectjrt:1.8.9'
    3}
    

應用

我們在項目中經常會遇到一個小問題,就是你對一個View綁定的一個點擊事件用戶瘋狂的快速點擊導致點擊事件的處理代碼被重複執行,常見的處理方式就是在點擊事件中加入時間判斷的邏輯,在短時間內的重複點擊不做響應。但是如果有很多點擊事件,這樣處理起來顯然讓代碼不好看。

所以,藉助AspectJ中的AOP思想,可以在解決快速重複點擊的問題的同時,可以讓你的代碼看的更優雅一點。

第一步:自定義一個註解
1@Retention(RetentionPolicy.RUNTIME)
2@Target(ElementType.METHOD)
3public @interface IgnoreFastClick {
4    long value() default 2000;
5}
第二步:寫Aspect植入的類
 1@Aspect
 2public class IgnoreFastClickAspect {
 3
 4    int lastViewId=-1;
 5    long lastClickTime=0;
 6
 7    @Pointcut("execution(@com.bob.www.testdemo.aop.IgnoreFastClick * *(..))")
 8    public void hhh(){
 9    }
10
11    @Around("hhh()")
12    public void insertCodeBlock(ProceedingJoinPoint joinPoint) throws Throwable {
13        View view;
14        //取click方法中的參數view
15        if (joinPoint.getArgs() != null
16                && joinPoint.getArgs().length > 0
17                && joinPoint.getArgs()[0] instanceof View) {
18            view = ((View) joinPoint.getArgs()[0]);
19            if (view == null)
20                return;
21        } else {
22            return;
23        }
24
25        MethodSignature methodSignature = ((MethodSignature) joinPoint.getSignature());
26        Method method = methodSignature.getMethod();
27        if (method.isAnnotationPresent(IgnoreFastClick.class)) {
28            IgnoreFastClick ignoreFastClick = method.getAnnotation(IgnoreFastClick.class);
29            long nowTime = System.currentTimeMillis();
30            // 如果兩次點擊時間差小於或等於value的值,並且兩次點擊的是同一個View,就不執行onClick()方法
31            if (nowTime - lastClickTime <= ignoreFastClick.value()
32                    && view.getId() == lastViewId) {
33                Log.d("AOP", "you click is too fast!");
34            } else {
35                // 記住上一次點擊的時間戳和View的ID
36                lastViewId = view.getId();
37                lastClickTime = nowTime;
38                執行onCLick()方法
39                joinPoint.proceed();
40            }
41        }
42    }
43}
第三步:給click事件方法加註解
 1    @Override
 2    protected void onCreate(Bundle savedInstanceState) {
 3        super.onCreate(savedInstanceState);
 4        setContentView(R.layout.activity_main);
 5
 6        mTestBtn = findViewById(R.id.btn_test);
 7        mTestBtn.setOnClickListener(new View.OnClickListener() {
 8
 9            @IgnoreFastClick
10            @Override
11            public void onClick(View v) {
12                Log.d("AOP", "----------------"+number++);
13            }
14        });
15    }

以後只要做防重點擊的事件,只用加個註解就搞定了。

要想完全掌握AspectJ的語法還是挺多的,這裏只是一個簡單的拋磚引玉的例子哦。讀者可以試試使用AspectJ完成事件統計相關的邏輯哦。講的不好,僅供參考。

如果覺得本文對你有一點點的幫助,關注一下又能有什麼損失呢????

發佈了60 篇原創文章 · 獲贊 13 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章