项目地址:aicareles/AopArms
简介: AopArms 编写了 Android 开发中常用的一套注解,如日志、异步处理、缓存、SP、延迟操作、定时任务、重试机制、try-catch 安全机制、过滤频繁点击、拦截等,后续还会有更多更强大的注解功能加入
更多:作者 提 Bug
标签:
一、简介
当下 Java 后端的 SpringBoot 微服务框架大火,原因离不开注解的使用,其简单易配置的注解方式使得更多的社区为其编写适用于 SpringBoot 的框架,也就是注解逐渐取代了传统的 xml 配置方式。那么注解在 Android 中也同样的得到了升华,著名的框架有 ButterKnife、 Dagger2、Retrofit 等等。今天带来一款 Android 中比较实用的注解框架AopArms,其用法简单,里面编写了 Android 开发中常用的一套注解,如日志、异步处理、缓存、SP、延迟操作、定时任务、重试机制、try-catch 安全机制、过滤频繁点击等,后续还会有更多更强大的注解功能加入。 本篇主要内容讲解在 Android 中的基本用法,关于 AOP 在 Android 中的实践请参考另外一篇Android 开发之 AOP 编程。
二、引入方式
1、在主工程中添加依赖
//引入 aspectjx 插件
apply plugin: 'android-aspectjx'
dependencies {
...
implementation 'cn.com.superLei:aop-arms:1.0.4'
}
2、项目跟目录的 gradle 脚本中加入
buildscript {
repositories {
mavenCentral()
}
dependencies {
//该库基于沪江 aspect 插件库
classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.4'
}
}
3、在 Application 中初始化
AopArms.init(this);
三、基本使用
1、缓存篇(可缓存任意类型)
1、插入缓存
/**
* key:缓存的键
* expiry:缓存过期时间,单位 s
* @return 缓存的值
*/
@Cache(key = "userList", expiry = 60 * 60 * 24)
private ArrayList initData() {
ArrayList list = new ArrayList<>();
for (int i=0; i<5; i++){
User user = new User();
user.setName("艾神一不小心:"+i);
user.setPassword("密码:"+i);
list.add(user);
}
return list;
}
2、获取缓存
private ArrayList getUser() {
return ArmsCache.get(this).getAsList("userList", User.class);
}
3、移除缓存
/**
* key:缓存的键
* beforeInvocation:缓存的清除是否在方法之前执行, 如果出现异常缓存就不会清除 默认 false
* allEntries:是否清空所有缓存(与 key 互斥) 默认 false
*/
@CacheEvict(key = "userList", beforeInvocation = true, allEntries = false)
public void removeUser() {
Log.e(TAG, "removeUser: >>>>");
}
2、SharedPreferences 篇(可保存对象)
1、保存 key 到 sp
@Prefs(key = "article")
private Article initArticle() {
Article article = new Article();
article.author = "jerry";
article.title = "hello android";
article.createDate = "2019-05-31";
article.content = "this is a test demo";
return article;
}
2、从 sp 中移除 key
/**
* key:sp 的键
* allEntries:是否清空所有存储(与 key 互斥) 默认 false
*/
@PrefsEvict(key = "article", allEntries = false)
public void removeArticle() {
Log.e(TAG, "removeArticle: >>>>");
}
3、通过 key 从 sp 中获取 value
public void getArticle() {
Article article = ArmsPreference.get(this, "article", null);
Log.e(TAG, "getArticle: "+article);
}
3、异步篇
@Async
public void asyn() {
Log.e(TAG, "useAync: "+Thread.currentThread().getName());
}
4、try-catch 安全机制篇
//自动帮你 try-catch 允许你定义回调方法
@Safe(callBack = "throwMethod")
public void safe() {
String str = null;
str.toString();
}
//自定义回调方法(注意要和 callBack 的值保持一致),必须要有 Callback 注解
@Callback
public void throwMethod(Throwable throwable){
Log.e(TAG, "throwMethod: >>>>>"+throwable.toString());
}
5、重试机制篇
/**
* @param count 重试次数
* @param delay 每次重试的间隔
* @param asyn 是否异步执行
* @param retryCallback 自定义重试结果回调
* @return 当前方法是否执行成功
*/
@Retry(count = 3, delay = 1000, asyn = true, retryCallback = "retryCallback")
public boolean retry() {
Log.e(TAG, "retryDo: >>>>>>"+Thread.currentThread().getName());
return false;
}
@Callback
public void retryCallback(boolean result){
Log.e(TAG, "retryCallback: >>>>"+result);
}
6、定时任务篇
/**
* @param interval 初始化延迟
* @param interval 时间间隔
* @param timeUnit 时间单位
* @param count 执行次数
* @param taskExpiredCallback 定时任务到期回调
*/
@Scheduled(interval = 1000L, count = 10, taskExpiredCallback = "taskExpiredCallback")
public void scheduled() {
Log.e(TAG, "scheduled: >>>>");
}
@Callback
public void taskExpiredCallback(){
Log.e(TAG, "taskExpiredCallback: >>>>");
}
7、延迟任务篇
//开启延迟任务(10s 后执行该方法)
@Delay(key = "test", delay = 10000L)
public void delay() {
Log.e(TAG, "delay: >>>>>");
}
//移除延迟任务
@DelayAway(key = "test")
public void cancelDelay() {
Log.e(TAG, "cancelDelay: >>>>");
}
8、过滤频繁点击
//value 默认 500ms
@OnClick({R.id.singleClick1, R.id.singleClick, R.id.singleClick2})
@SingleClick(ids = {R.id.singleClick, R.id.singleClick2})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.singleClick1:
Log.e("singleClick", "我不防抖");
break;
case R.id.singleClick:
Log.e("singleClick", "我防抖");
break;
case R.id.singleClick2:
Log.e("singleClick", "我防抖 2");
break;
}
}
9、拦截篇(如登录)
1、在需要进行拦截的方法添加注解
@Intercept("login_intercept")
public void loginIntercept() {
Log.e(TAG, "intercept: 已登陆>>>>");
}
2、(建议,统一处理)在 Application 中进行进行监听拦截回调
public class MyApplication extends Application {
private static final String TAG = "MyApplication";
private static MyApplication mApplication;
@Override
public void onCreate() {
super.onCreate();
mApplication = this;
AopArms.init(this);
AopArms.setInterceptor(new Interceptor() {
@Override
public boolean intercept(String key, String methodName) throws Throwable {
Log.e(TAG, "intercept methodName:>>>>>"+methodName);
if ("login_intercept".equals(key)){
String userId = ArmsPreference.get(mApplication, "userId", "");
if (TextUtils.isEmpty(userId)){
Toast.makeText(mApplication, "您还没有登录", Toast.LENGTH_SHORT).show();
return true;//代表拦截
}
}
return false;//放行
}
});
}
}
10、动态授权篇
1、开启请求权限
/**
* @param value 权限值
* @param rationale 拒绝后的下一次提示(开启后,拒绝后,下一次会先提示该权限申请提示语)
* @param requestCode 权限请求码标识
*/
@Permission(value = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, rationale = "为了更好的体验,请打开相关权限")
public void permission(View view) {
Log.e(TAG, "permission: 权限已打开");
}
2、请求拒绝注解回调
@PermissionDenied
public void permissionDenied(int requestCode, List denyList){
Log.e(TAG, "permissionDenied: "+requestCode);
Log.e(TAG, "permissionDenied>>>: "+denyList.toString());
}
3、请求拒绝且不在提示注解回调
@PermissionNoAskDenied
public void permissionNoAskDenied(int requestCode, List denyNoAskList){
Log.e(TAG, "permissionNoAskDenied: "+requestCode);
Log.e(TAG, "permissionNoAskDenied>>>: "+denyNoAskList.toString());
//前往设置页面打开权限
AopPermissionUtils.showGoSetting(this, "为了更好的体验,建议前往设置页面打开权限");
}
四、混淆
#AopArms
-keepclassmembers class * {
@cn.com.superLei.aoparms.annotation.Callback ;
}
五、参考