AOP切面編程在android上的應用

前言

切面編程一直是一個熱點的話題,這篇文章講講一個第三方aop庫在android上的應用。

本篇文章參考以下鏈接:
AOP第三方庫

這章涉及到以下內(nèi)容:

  1. aop庫的配置
  2. aop導入問題解決
  3. aop的使用
  4. aop混淆
一. aop庫的配置

在你的porject的build.gradle中做以下配置:

buildscript {
    
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0'

        //AOP切面編程依賴
        classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:1.1.1'
        classpath 'org.aspectj:aspectjtools:1.8.13'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

在 app module 的buildle.gradle中做如下配置:

 //AOP切面編程依賴
    compile 'com.safframework:saf-aop:1.2.0'
    //rxjava2.x
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    compile 'io.reactivex.rxjava2:rxjava:2.1.0'
    //AOP切面編程Cache依賴
    implementation 'com.safframework:saf-cache:1.1.0'
    implementation 'tony-common:tony-common-utils:1.2.4'
    //AOP切面編程Log依賴
    implementation 'com.safframework.log:saf-log:1.5.0'
    //AOP切面編程AppPrefs依賴
    implementation 'com.safframework.injectview:saf-injectview:1.0.0'
    annotationProcessor 'com.safframework.injectview:saf-injectview-compiler:1.0.0'

需要注意的是,AOP庫使用的時候,也要添加RxJava2.X的引用。

二. aop導入問題解決

在導入切面編程庫依賴的時候,可能會出現(xiàn)如下問題:

Error:Execution failed for task ':app:transformClassesWithExtractJarsForDebug'.
> Unexpected scopes found in folder 'C:\my_demo_test\TestDemo\app\build\intermediates\transforms\AspectTransform\debug'. 
Required: SUB_PROJECTS. Found: 
EXTERNAL_LIBRARIES, PROJECT, SUB_PROJECTS

解決方案如下:

造成上述問題是由于as版本,需將Android studio的instant run關(guān)閉。具體如下: 
Settings → Build, Execution, Deployment → Instant Run and uncheck Enable Instant Run.

配圖如下:

image.png

解決此方法,大家也可以參考鏈接
android aspectJ報錯“transformClassesWithExtractJarsForDebug“

三. aop的使用

AOP涉及的注解有以下幾個:


image.png

下面對各注解依次講解:

3.1 Async異步注解

使用類似如下:

  @Async
    private void AsyncTest(){
        LogUtil.e("====當前線程===="+Thread.currentThread().getId());
        LogUtil.e("====主線程===="+ Looper.getMainLooper().getThread().getId());
    }

在主線程中調(diào)用 AsyncTest 方法,會發(fā)現(xiàn)其運行在一個不同于主線程的子線程中。

3.2 Cacheable緩存注解

存儲數(shù)據(jù)如下:

    @Cacheable(key = "name")
    private String putCache(){
        return "我是誰";
    }

獲取緩存數(shù)據(jù):

  private String getCache(){
        Cache cache=Cache.get(CacheActivity.this);
        //Cache的存取方式就是Acache,只不過存儲地址改成了緩存而已
        String name=cache.getString("name");
        return name;
    }
3.3 Log注解

你可以類似這樣使用:

    @LogMethod
    private void log1(){
        LogUtil.e("=====log1======");
    }

    @LogMethod
    private String log2(String s){
        LogUtil.e("=====log2======"+s);
        return s;
    }

然后在需要用到的地方直接調(diào)用 log1 和 log2 方法就可以打印log了,它最大的好處是不會在代碼中穿插各種 Log代碼。

3.4 Hook注解

使用范例:

   @HookMethod(beforeMethod = "before",afterMethod = "after")
   private void getMachine(){
       LogUtil.e("======getMachine=====");
   }

   private void before(){
       LogUtil.e("====開始時間=======");
   }

    private void after(){
        LogUtil.e("====結(jié)束時間=======");
    }

然后在調(diào)用getMachine方法的時候,你會收到這樣的log


image.png

這個可以用來監(jiān)測一個方法執(zhí)行的用時,當然,你在聲明Hook注解的時候必須包含 beforeMethod,afterMethod中的一個或同時具有,若不聲明,則Hook使用無效

3.5 Prefs注解

類似手機上的文件存儲,存值你可以這樣操作:

  @Prefs(key = "key")
    private String putPrefs(){
        return "大家好";
    }

取值是這樣的:

  private String getPrefs(){
        AppPrefs appPrefs=AppPrefs.get(PrefsActivity.this);
        String key=appPrefs.getString("key",null);
        return key;
    }
3.6 safe注解

保證代碼執(zhí)行安全的,若不想代碼拋出異常,你可以這樣處理:

   @Safe
    private void testStringLength(){
        String msg=null;
        int length=msg.length();
    }

這樣,你在調(diào)用 testStringLength 方法的時候就不會報錯了。

3.6 Trace注解

可以用來監(jiān)測方法執(zhí)行時長,使用時類似這樣:

  @Trace
    private void testTrace(){

        Observable.create(new ObservableOnSubscribe<String>() {
            @Trace
            @Override
            public void subscribe(@NonNull ObservableEmitter<String> e) throws Exception {

                e.onNext("111");


            }
        }).subscribe(new Consumer<String>() {

            @Trace
            @Override
            public void accept(@NonNull String str) throws Exception {

            }
        });
    }

調(diào)用 testTrace 方法之后,在log 的 i 級別中,你可以看到這樣的log


image.png

這里,我們就可以很清楚的看到每個方法的執(zhí)行時間了。

四. 混淆

混淆的話,可以這樣處理

-keep class com.safframework.aop.** { *; }

ok,今天就講到這里,謝謝誒。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,150評論 25 708
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,890評論 18 139
  • title: Android AOP之字節(jié)碼插樁author: 陶超description: 實現(xiàn)數(shù)據(jù)收集SDK時...
    陶菜菜閱讀 38,266評論 40 182
  • 算法一直是我們重視的話題的主人,什么樣的網(wǎng)站HITS算法,我們都知道,期望站長們是準確的,它沒有再加鼓勵,它逐一清...
    蘇小魂閱讀 264評論 0 0
  • 今天早上孩子不到6點就醒了,醒了后來到了我們的房間,看到她這么早醒了,我也跟著起來了,跟她一起復習了以前學...
    李梓旭媽媽閱讀 104評論 0 1