国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android AOP框架AspectJ使用詳解

2019-10-22 18:22:55
字體:
來源:轉載
供稿:網友

前言

之前了解過android的AOP框架,用法主要用來打日志;現在有一個需求需要函數在新線程中執行,并且函數主體執行完之后,在UI線程返回結果。想到手寫的話,每次都要new Thread的操作,比較麻煩;因此就嘗試用注解的方法解決這個問題。

AspectJ的使用核心就是它的編譯器,它就做了一件事,將AspectJ的代碼在編譯期插入目標程序當中,運行時跟在其它地方沒什么兩樣,因此要使用它最關鍵的就是使用它的編譯器去編譯代碼ajc。ajc會構建目標程序與AspectJ代碼的聯系,在編譯期將AspectJ代碼插入被切出的PointCut中,已達到AOP的目的。

因此,無論在什么IDE上(如果使用命令行就可以直接使用ajc編譯了),問題就是讓IDE使用ajc作為編譯器編譯代碼。

代碼實現

注解使用

代碼主要通過TraceLog、RunOnNewThread、RunOnNewThreadWithUICallback這三個注解與AOP容器關聯。使用方法如下:

@TraceLog@RunOnNewThreadpublic void checkAndRestartDownloadTask(final boolean isAutoCache) { DownloadManager.getInstance().startService(isAutoCache);}@TraceLog@RunOnNewThreadWithUICallbackpublic Boolean isShowTipsForFirstVideoCache(DBQueryCallback<Boolean> callback) { if (!PreferenceClient.is_first_video_cache_done.getBoolean() &&   (DownloadManager.getInstance().getFinishedTaskSize(true, false) > 0 ||     DownloadManager.getInstance().getFinishedTaskSize(true, true) > 0)) {  PreferenceClient.is_first_video_cache_done.setBoolean(true);  return true; } return false;}

checkAndRestartDownloadTask方法,希望方法體在一個新的線程執行并打印方法執行的Log;isShowTipsForFirstVideoCache方法,希望方法體在一個新的線程執行,并將函數的結果通過DBQueryCallback這個回調回傳給UI線程,同時打印方法執行的Log。

AOP容器識別這三個注解,并實現注解解釋器。

@Aspectpublic class TudouDownloadAspect { public static final String TAG = TudouDownloadAspect.class.getSimpleName(); private static final String THREAD_CALLBACK_POINT_METHOD =   "execution(@com.download.common.aspect.RunOnNewThreadWithUICallback * *(.., com.download.common.callback.DBQueryCallback))"; private static final String THREAD_CALLBACK_POINT_CONSTRUCTOR =   "execution(@com.download.common.aspect.RunOnNewThreadWithUICallback *.new(.., com.download.common.callback.DBQueryCallback))"; private static final String THREAD_POINT_METHOD =   "execution(@com.download.common.aspect.RunOnNewThread * *(..))"; private static final String THREAD_POINT_CONSTRUCTOR =   "execution(@com.download.common.aspect.RunOnNewThread *.new(..))"; private static final String LOG_POINT_METHOD =   "execution(@com.download.common.aspect.TraceLog * *(..))"; private static final String LOG_POINT_CONSTRUCTOR =   "execution(@com.download.common.aspect.TraceLog *.new(..))"; @Pointcut(THREAD_CALLBACK_POINT_METHOD) public void methodAnnotatedWithThread(){} @Pointcut(THREAD_CALLBACK_POINT_CONSTRUCTOR) public void constructorAnnotatedWithThread(){} @Pointcut(THREAD_POINT_METHOD) public void methodAnnotatedWithNewThread(){} @Pointcut(THREAD_POINT_CONSTRUCTOR) public void constructorAnnotatedWithNewThread(){} @Pointcut(LOG_POINT_METHOD) public void methodAnnotatedWithLog(){} @Pointcut(LOG_POINT_CONSTRUCTOR) public void constructorAnnotatedWithLog(){} /**  * @RunOnNewThreadWithUICallback 的注解解釋器  * */ @Around("methodAnnotatedWithThread() || constructorAnnotatedWithThread()") public Object wrapNewThreadWithCallback(final ProceedingJoinPoint joinPoint) throws Throwable {  Log.v(TAG, "in wrapNewThreadWithCallback");  Object[] objs = joinPoint.getArgs();  final DBQueryCallback callback = (DBQueryCallback) objs[objs.length-1];  new Thread(new Runnable() {   @Override   public void run() {    try {     final Object obj = joinPoint.proceed();     DownloadClient.getInstance().mainHandler.post(new Runnable() {      @Override      public void run() {       if (obj != null)        callback.querySuccess(obj);       else        callback.queryFail();      }     });    } catch (Throwable throwable) {     throwable.printStackTrace();    }   }  }).start();  return null; } /**  * @RunOnNewThread 的注解解釋器  * */ @Around("methodAnnotatedWithNewThread() || constructorAnnotatedWithNewThread()") public void wrapNewThread(final ProceedingJoinPoint joinPoint) throws Throwable {  Log.v(TAG, "in wrapNewThread");  new Thread(new Runnable() {   @Override   public void run() {    try {     joinPoint.proceed();    } catch (Throwable throwable) {     throwable.printStackTrace();    }   }  }).start(); } /**  * @TraceLog 的注解解釋器  * */ @Before("methodAnnotatedWithLog() || constructorAnnotatedWithLog()") public void wrapWithLog(JoinPoint joinPoint) throws Throwable {  Log.v(TAG, "before->" + joinPoint.getTarget().toString() + "---" + joinPoint.getSignature().getName()); }}
  1. @Aspect:聲明一個AOP容器
  2. @Pointcut:聲明一個切入點
  3. @Around:將函數主體包裹起來,在函數主體前、后插入代碼
  4. @Before:在函數主體執行之前插入代碼

使用Gradle腳本加載AOP容器

buildscript {  repositories {    mavenLocal()    maven { url "https://jitpack.io" }  }  dependencies {    classpath 'org.aspectj:aspectjtools:1.8.+' //AspectJ腳本依賴  }} dependencies {    compile 'org.aspectj:aspectjrt:1.8.+' //AspectJ 代碼依賴  }//AspectJ AOP容器加載腳本final def log = project.loggerfinal def variants = project.android.libraryVariantsvariants.all { variant ->  JavaCompile javaCompile = variant.javaCompile  javaCompile.doLast {    String[] args = ["-showWeaveInfo",             "-1.5",             "-inpath", javaCompile.destinationDir.toString(),             "-aspectpath", javaCompile.classpath.asPath,             "-d", javaCompile.destinationDir.toString(),             "-classpath", javaCompile.classpath.asPath,             "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]    log.debug "ajc args: " + Arrays.toString(args)    MessageHandler handler = new MessageHandler(true);    new Main().run(args, handler);    for (IMessage message : handler.getMessages(null, true)) {      switch (message.getKind()) {        case IMessage.ABORT:        case IMessage.ERROR:        case IMessage.FAIL:          log.error message.message, message.thrown          break;        case IMessage.WARNING:          log.warn message.message, message.thrown          break;        case IMessage.INFO:          log.info message.message, message.thrown          break;        case IMessage.DEBUG:          log.debug message.message, message.thrown          break;      }    }  }}

備注

@RunOnNewThreadWithUICallback這個注解的匹配規則需要函數的最后一個參數為DBQueryCallback(必須要有一個回調參數,不然怎么回傳給UI線程~)。函數的返回值必須和DBQueryCallback的泛型類型一致,因為需要將返回值傳入回調當中;

new Thread(new Runnable() {   @Override   public void run() {    try {     final Object obj = joinPoint.proceed();     DownloadClient.getInstance().mainHandler.post(new Runnable() {      @Override      public void run() {       if (obj != null)        callback.querySuccess(obj);       else        callback.queryFail();      }     });    } catch (Throwable throwable) {     throwable.printStackTrace();    }   }  }).start();

注意final Object obj = joinPoint.proceed();,執行了函數體以后,我們默認取到的是一個Object類型的返回值,所以不能用基本數據類型(bool用Boolean,int用Interger)。還有一點,Java中的null是可以轉化為任意類型的,所以就算在函數體直接返回null,執行final Object obj = joinPoint.proceed();,這個類型轉化也是不會有問題。親測有效,可以放心使用

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 礼泉县| 兴山县| 库车县| 筠连县| 大姚县| 扎鲁特旗| 湟中县| 元氏县| 英吉沙县| 嘉兴市| 泊头市| 中超| 祁门县| 利川市| 布尔津县| 临洮县| 城步| 麻栗坡县| 华宁县| 平阳县| 隆德县| 阳原县| 麟游县| 兰西县| 九寨沟县| 张家港市| 淮南市| 手游| 灌南县| 金山区| 临桂县| 库车县| 车险| 巴彦淖尔市| 罗城| 上思县| 无锡市| 南昌县| 衡阳县| 临江市| 宜川县|