Android线程创建aop,Android AOP框架AspectJ使用详解

前言

之前了解过android的AOP框架,用法主要用来打日志;现在有一个需求需要函数在新线程中执行,并且函数主体执行完之后,在UI线程返回结果。想到手写的话,每次都要new Thread的操作,比较麻烦;因此就尝试用注解的方法解决这个问题。

AspectJ的使用核心就是它的编译器,它就做了一件事,将AspectJ的代码在编译期插入目标程序当中,运行时跟在其它地方没什么两样,因此要使用它最关键的就是使用它的编译器去编译代码ajc。ajc会构建目标程序与AspectJ代码的联系,在编译期将AspectJ代码插入被切出的PointCut中,已达到AOP的目的。

因此,无论在什么IDE上(如果使用命令行就可以直接使用ajc编译了),问题就是让IDE使用ajc作为编译器编译代码。

代码实现

注解使用

代码主要通过TraceLog、RunOnNewThread、RunOnNewThreadWithUICallback这三个注解与AOP容器关联。使用方法如下:

@TraceLog

@RunOnNewThread

public void checkAndRestartDownloadTask(final boolean isAutoCache) {

DownloadManager.getInstance().startService(isAutoCache);

}

@TraceLog

@RunOnNewThreadWithUICallback

public Boolean isShowTipsForFirstVideoCache(DBQueryCallback 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容器识别这三个注解,并实现注解解释器。

@Aspect

public 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());

}

}

@Aspect:声明一个AOP容器

@Pointcut:声明一个切入点

@Around:将函数主体包裹起来,在函数主体前、后插入代码

@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.logger

final def variants = project.android.libraryVariants

variants.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();,这个类型转化也是不会有问题。亲测有效,可以放心使用

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值