生成gradle插件步骤
- create new Module
- select Android Library
- 把生成的module(例如:plugin)里面的东西都删除(除了build.gradle,但是要被gradle里面的所有内容删除)
- 在plugin里面新增一个“src”文件夹,往src文件夹新增main文件夹,再往main文件夹新增groovy和resources文件夹。
- resources目录下新建文件夹META-INF,META-INF文件夹下新建gradle-plugins文件夹。
- 在groovy目录下新建项目包名,就像Java包名那样。
[图片上传失败...(image-9a417b-1549967634568)]
打开Module下的build.gradle文件,输入
apply plugin: 'groovy'
apply plugin: 'maven'
dependencies {
compile gradleApi()//gradle sdk
compile localGroovy()//groovy sdk
compile 'com.android.tools.build:gradle:2.2.2'
compile 'org.javassist:javassist:3.20.0-GA'
compile 'org.aspectj:aspectjtools:1.8.1'
}
uploadArchives {
repositories.mavenDeployer {
repository(url: uri('../repo'))
pom.groupId = 'com.dawn.plugin'
pom.artifactId = 'gradleplugin'
pom.version = '1.0.0'
}
}
repositories {
jcenter()
}
uploadArchives闭包里面配置的是将插件发布到本地仓库。
上面的group和version的定义会被使用,作为maven库的坐标的一部分,group会被作为坐标的groupId,version会被作为坐标的version,而坐标的artifactId组成即module名,我们让其取一个别名moduleName。然后maven本地仓库的目录就是当前项目目录下的repo目录。
下面我们在groovy下的包名下新建一个文件,命名为AspectjPlugin.groovy,注意有groovy后缀,然后在里面输入,注意包名替换为你自己的包名。
package com.dawn.plugin
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
import org.gradle.api.Plugin
import org.gradle.api.Project
/**
* @使用ajc编译java代码 , 同 时 织 入 切 片 代 码
* 使用 AspectJ 的编译器(ajc,一个java编译器的扩展)
* 对所有受 aspect 影响的类进行织入。
* 在 gradle 的编译 task 中增加额外配置,使之能正确编译运行。
*/
public class AspectjPlugin implements Plugin {
void apply(Project project) {
project.dependencies {
compile 'org.aspectj:aspectjrt:1.8.9'
}
final def log = project.logger
log.error "========================";
log.error "Aspectj切片开始编织Class!";
log.error "========================";
project.android.applicationVariants.all { variant ->
def javaCompile = variant.javaCompile
javaCompile.doLast {
String[] args = ["-showWeaveInfo",
"-1.8",
"-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;
}
}
}
}
}
}
然后在resources/META-INF/gradle-plugins目录下新建一个properties文件,注意该文件的命名就是你只有使用插件的名字,这里命名为com.dawn.plugin.aspectj.properties,在里面输入
implementation-class=com.dawn.plugin.AspectjPlugin
这时候,右侧的gradle Toolbar就会在module下多出一个task
[图片上传失败...(image-38a5d8-1549967634568)]
点击uploadArchives这个Task,就会在项目下多出一个repo目录,里面存着这个gradle插件。
以及在根目录的build.gradle文件添加配置:
repositories {
//...
maven{
url uri('repo')
}
}
dependencies {
//...
classpath 'com.dawn.plugin:gradleplugin:1.0.0'
}
先Rebuild Project,最后在app下的build.gradle添加配置
import com.dawn.plugin.AspectjPlugin
apply plugin: AspectjPlugin
//...
compile 'org.aspectj:aspectjrt:1.8.9'
一、防止View短时间内多次点击
1. 自定义注解
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface SingleClick {
}
2. SingleClickAspect
@Aspect
public class SingleClickAspect {
static int TIME_TAG = R.id.click_time;
public static final int MIN_CLICK_DELAY_TIME = 1000;//间隔时间600ms
//execution方法里面要填写你自己的完整的包名路径:xxx.xxx.xxx.SingleClick
@Pointcut("execution(@dawn.com.aspectjdemo.SingleClick * *(..))")
public void methodAnnotated() {
}
@Around("methodAnnotated()")
public void aroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable{
View view=null;
for (Object arg :joinPoint.getArgs()){
if(arg instanceof View ){
view =(View)arg;
}
}
if(view!=null){
Object tag=view.getTag(TIME_TAG);
long lastClickTime= ((tag != null) ? (long) tag : 0);
LogUtils.showLog( "lastClickTime:" + lastClickTime);
long currentTime= Calendar.getInstance().getTimeInMillis();
if(currentTime -lastClickTime >MIN_CLICK_DELAY_TIME){//过滤掉600毫秒内的连续点击
view.setTag(TIME_TAG,currentTime);
LogUtils.showLog( "currentTime:" + currentTime);
joinPoint.proceed();//执行原方法
}
}
}
}
使用方法:标注在onClick上
@SingleClick public void onClick(View view) {
...
}
或者任何参数内有view可以做为参照系(view可以不是onClick的view,仅仅作为时间tag依附对象作为参照)的方法上,例如TRouter的页面跳转,防止连续快速点击重复跳页现象:
public class RouterHelper { @SingleClick // 防止连续点击 public static void go(String actionName, HashMap data, View view) { TRouter.go(actionName, data, view); } }
二、拦截未登录用户的权限
1.自定义注解
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface CheckLogin {
}
2. CheckLoginAspect
@Aspect
public class CheckLoginAspect {
@Pointcut("execution(@dawn.com.aspectjdemo.annotation.CheckLogin * *(..))")
public void methodCheckLogin() {
}
@Around("methodCheckLogin()")
public void aroundCheckLogin(ProceedingJoinPoint joinPoint) throws Throwable {
if (null == UserInfoSp.getUser()) {
LogUtils.showLog("还未登录,请先登录");
//跳转到登录界面
return;
}
joinPoint.proceed();//执行原方法
}
}
使用方法,标注要某方法上 :
@CheckLogin
@Override
public void onClick(View view) {
Toast.makeText(this, "获取用户信息", Toast.LENGTH_SHORT).show();
}