12个Android中使用AspectJ实现AOP的实例操作

}

Log.i(TAG, “this is an insert log.”);

}

2. 防止快速点击


  1. 功能

防止段时间内对view控件的多次点击,这里可以设置时间间隔,即多长时间内不能多次点击。

  1. annotation

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface SingleClick {

long value() default 1000L;

int[] ids() default {View.NO_ID}; //支持多个值

}

  1. aspectj

@Aspect

public class SingleClickAspect {

private final String TAG = “SingleClickAspect”;

private static int TIME_TAG = R.id.click_time;

@Pointcut(“execution(@com.androidwind.quickaop.library.annotation.SingleClick * *(…))”)

public void onSingleClickMethod() {

}

@Around(“onSingleClickMethod() && @annotation(singleClick)”)

public void doSingleClickMethod(ProceedingJoinPoint joinPoint, SingleClick singleClick) throws Throwable {

Log.d(“SingleClickAspect”, “singleClick=” + singleClick.hashCode());

View view = null;

for (Object arg : joinPoint.getArgs()) {

if (arg instanceof View) {

view = (View) arg;

break;

}

}

if (view != null) {

Object tag = view.getTag(TIME_TAG);

long lastClickTime = ((tag != null) ? (long) tag : 0);

Log.d(“SingleClickAspect”, “lastClickTime:” + lastClickTime);

long currentTime = Calendar.getInstance().getTimeInMillis();

long value = singleClick.value();

int[] ids = singleClick.ids();

if (currentTime - lastClickTime > value || !hasId(ids, view.getId())) {

view.setTag(TIME_TAG, currentTime);

Log.d(“SingleClickAspect”, “currentTime:” + currentTime);

joinPoint.proceed();//执行原方法

}

}

}

public static boolean hasId(int[] arr, int value) {

for (int i : arr) {

if (i == value)

return true;

}

return false;

}

}

  1. 使用方法

@SingleClick(value = 2000L, ids = {R.id.singleClick1})

public void singleClick1(View view) {

Log.i(TAG, “this is a single click log.”);

}

@SingleClick(ids = {R.id.singleClick2})

public void singleClick2(View view) {

Log.i(TAG, “this is a single click log.”);

}

3. 登录态检测


  1. 功能

检测当前是否已经登录,如果登录继续执行,如果没登录则提示。

  1. annotation

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.METHOD})

public @interface CheckLogin {

}

  1. aspectj

@Aspect

public class CheckLoginAspect {

private final String TAG = “CheckLoginAspect”;

private final String POINTCUT = “execution(@com.androidwind.quickaop.annotation.CheckLogin * *(…))”;

@Pointcut(POINTCUT)

public void onCheckLoginMethod() {

}

@Around(“onCheckLoginMethod()”)

public void doCheckLoginMethod(ProceedingJoinPoint joinPoint) throws Throwable {

if (MyApplication.isLogin()) {

joinPoint.proceed();//执行原方法

} else {

Toast.makeText(MyApplication.getApplication(), “还未登录”, Toast.LENGTH_SHORT).show();

}

}

}

  1. 使用方法

@CheckLogin

public void checkLogin(View view) {

Log.i(TAG, “this is an operation after login.”);

}

4. 请求权限


  1. 功能

在执行方法前检测app是否已经获得了相应的权限。

这里引入RxPermissions作为权限检测工具。

  1. annotation

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.METHOD})

public @interface RequirePermission {

String[] value();

}

  1. aspectj

@Aspect

public class RequirePermissionAspect {

private final String TAG = “RequirePermissionAspect”;

private final String POINTCUT = “execution(@com.androidwind.quickaop.annotation.RequirePermission * *(…))”;

@Pointcut(POINTCUT)

public void onRequirePermissionMethod() {

}

@Around(“onRequirePermissionMethod() && @annotation(requirePermission)”)

public void doRequirePermissionMethod(ProceedingJoinPoint joinPoint, RequirePermission requirePermission) throws Throwable {

FragmentActivity activity = null;

final Object object = joinPoint.getThis();

if (object instanceof FragmentActivity) {

activity = (FragmentActivity) object;

} else if (object instanceof Fragment) {

activity = ((Fragment) object).getActivity();

}

if (activity == null) {

joinPoint.proceed();

} else {

new RxPermissions(activity)

.request(requirePermission.value())

.subscribe(new Consumer() {

@Override

public void accept(Boolean granted) throws Exception {

if (granted) { // Always true pre-M

try {

joinPoint.proceed();

} catch (Throwable throwable) {

throwable.printStackTrace();

}

} else {

Toast.makeText(MyApplication.getApplication(), “授权失败!”, Toast.LENGTH_SHORT).show();

}

}

});

}

}

}

  1. 使用方法

@RequirePermission(value = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE})

public void requirePermission(View view) {

Toast.makeText(MyApplication.getApplication(), “授权成功,继续进行”, Toast.LENGTH_SHORT).show();

}

5. 埋点


  1. 功能

添加埋点信息,用于数据统计功能。

  1. annotation

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.METHOD})

public @interface EventTracking {

String key();

String value();

}

  1. aspectj

@Aspect

public class EventTrackingAspect {

private final String TAG = “EventTrackingAspect”;

private final String POINTCUT = “execution(@com.androidwind.quickaop.library.annotation.EventTracking * *(…))”;

@Pointcut(POINTCUT)

public void onEventTrackingMethod() {

}

@Around(“onEventTrackingMethod() && @annotation(eventTracking)”)

public void doEventTrackingMethod(ProceedingJoinPoint joinPoint, EventTracking eventTracking) throws Throwable {

String key = eventTracking.key();

String value = eventTracking.value();

SPUtils.getInstance().put(key, value);

joinPoint.proceed();

}

}

  1. 使用方法

@EventTracking(key = “1000”, value = “埋点值1”)

public void eventTracking(View view) {

Log.i(TAG, "this is an event tracking log, the eventTracking is " + SPUtils.getInstance().getString(“1000”));

}

6. 异步执行


  1. 功能

保证方法是通过异步方式执行,这里使用RxJava实现异步。

  1. annotation

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.METHOD})

public @interface Asynchronize {

}

  1. aspectj

@Aspect

public class AsynchronizeAspect {

private final String TAG = “AsynchronizeAspect”;

private final String POINTCUT = “execution(@com.androidwind.quickaop.annotation.Asynchronize * *(…))”;

@Pointcut(POINTCUT)

public void onAsynchronizeMethod() {

}

@Around(“onAsynchronizeMethod()”)

public void doAsynchronizeMethod(ProceedingJoinPoint joinPoint) throws Throwable {

Observable.create(new ObservableOnSubscribe() {

@Override

public void subscribe(ObservableEmitter emitter) throws Exception {

System.out.println(“[Thread Name-AsynchronizeAspect: ]” + Thread.currentThread().getName());

try {

joinPoint.proceed();

} catch (Throwable throwable) {

throwable.printStackTrace();

}

}

})

.subscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe();

}

}

  1. 使用方法

@Asynchronize

public void asynchronize(View view) {

System.out.println(“[Thread Name-asynchronize: ]” + Thread.currentThread().getName());

}

7. 异常捕获


  1. 功能

捕获此方法所可能产生的异常情况,保证执行此方法不会导致app崩溃。

  1. annotation

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.METHOD})

public @interface CatchException {

}

  1. aspectj

@Aspect

public class CatchExceptionAspect {

private final String TAG = “CatchExceptionAspect”;

private final String POINTCUT = “execution(@com.androidwind.quickaop.library.annotation.CatchException * *(…))”;

@Pointcut(POINTCUT)

public void onCatchExceptionMethod() {

}

@Around(“onCatchExceptionMethod()”)

public void doCatchExceptionMethod(ProceedingJoinPoint joinP
公种号:编程进阶路
oint) throws Throwable {

try {

joinPoint.proceed();

} catch (Exception e) {

LogUtils.e(TAG, getException(e));

}

}

private String getException(Throwable ex) {

StringWriter errors = new StringWriter();

ex.printStackTrace(new PrintWriter(errors));

return errors.toString();

}

}

  1. 使用方法

@CatchException

public void catchException(View view) {

String s = null;

s.toString();

}

8. Hook方法


  1. 功能

可以在执行某个方法的前和后,执行另外指定的方法。

  1. annotation

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.METHOD})

public @interface HookMethod {

String beforeMethod();

String afterMethod();

}

  1. aspectj

@Aspect

public class HookMethodAspect {

private final String TAG = “HookMethodAspect”;

private final String POINTCUT = “execution(@com.androidwind.quickaop.library.annotation.HookMethod * *(…))”;

@Pointcut(POINTCUT)

public void onHookMethodMethod() {

}

@Around(“onHookMethodMethod()”)

public void doHookMethodMethod(ProceedingJoinPoint joinPoint) throws Throwable {

MethodSignature signature = (MethodSignature) joinPoint.getSignature();

Method method = signature.getMethod();

HookMethod hookMethod = method.getAnnotation(HookMethod.class);

if (hookMethod == null) {

return;

}

String beforeMethod = hookMethod.beforeMethod();

String afterMethod = hookMethod.afterMethod();

if (!StringUtils.isEmpty(beforeMethod)) {

try {

ReflectUtils.reflect(joinPoint.getTarget()).method(beforeMethod);

} catch (ReflectUtils.ReflectException e) {

e.printStackTrace();

Log.e(TAG, "no method " + beforeMethod);

}

}

joinPoint.proceed();

if (!StringUtils.isEmpty(afterMethod)) {

try {

ReflectUtils.reflect(joinPoint.getTarget()).method(afterMethod);

} catch (ReflectUtils.ReflectException e) {

e.printStackTrace();

Log.e(TAG, "no method " + afterMethod);

}

}

}

}

  1. 使用方法

@HookMethod(beforeMethod = “beforeMethod”, afterMethod = “afterMethod”)

public void hookMethod(View view) {

Log.i(TAG, “this is a hookMethod”);

}

private void beforeMethod() {

Log.i(TAG, “this is a before method”);

}

private void afterMethod() {

Log.i(TAG, “this is an after method”);

}

9. 缓存


  1. 功能

将方法执行结果保存到缓存中,这里使用sharedpreferences。

  1. annotation

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface Cache {

String key();

}

  1. aspectj

@Aspect

public class CacheAspect {

private static final String POINTCUT_METHOD = “execution(@com.androidwind.quickaop.library.annotation.Cache * *(…))”;

@Pointcut(POINTCUT_METHOD)

public void onCacheMethod() {

}

@Around(“onCacheMethod() && @annotation(cache)”)

public Object doCacheMethod(ProceedingJoinPoint joinPoint, Cache cache) throws Throwable {

String key = cache.key();

Object result = joinPoint.proceed();

if (result instanceof String) {

SPUtils.getInstance().put(key, (String)result);

}

return result;

}

}

  1. 使用方法

@Cache(key = “name”)

public String cache(View view) {

return “Jerry”;

}

10. Null检查


  1. 功能

对入参进行null检测。

  1. annotation

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface NullCheck {

int position() default 0;//the input params position

}

  1. aspectj

@Aspect

public class NullCheckAspect {

private final String TAG = “NullCheckAspect”;

private final String POINTCUT = “execution(@com.androidwind.quickaop.library.annotation.NullCheck * *(…))”;

@Pointcut(POINTCUT)

public void onNullCheckMethod() {

}

@Around(“onNullCheckMethod() && @annotation(nullCheck)”)

public void doNullCheckMethod(ProceedingJoinPoint joinPoint, NullCheck nullCheck) throws Throwable {

int position = nullCheck.position();

Object[] objects = joinPoint.getArgs();

if (objects.length > 0 && position < objects.length) {

if (!ObjectUtils.isEmpty(objects[position])) {

joinPoint.proceed();

}

}

}

}

  1. 使用方法

public void nullCheck(View view) {

getString(“Tommy”, null);

}

@NullCheck(position = 1)

private void getString(String name, String country) {

Log.i(TAG, “this is after nullcheck input”);

}

总结

找工作是个很辛苦的事情,而且一般周期都比较长,有时候既看个人技术,也看运气。第一次找工作,最后的结果虽然不尽如人意,不过收获远比offer大。接下来就是针对自己的不足,好好努力了。

最后为了节约大家的时间,我把我学习所用的资料和面试遇到的问题和答案都整理成了PDF文档

喜欢文章的话请关注、点赞、转发 谢谢!

aspectj

@Aspect

public class NullCheckAspect {

private final String TAG = “NullCheckAspect”;

private final String POINTCUT = “execution(@com.androidwind.quickaop.library.annotation.NullCheck * *(…))”;

@Pointcut(POINTCUT)

public void onNullCheckMethod() {

}

@Around(“onNullCheckMethod() && @annotation(nullCheck)”)

public void doNullCheckMethod(ProceedingJoinPoint joinPoint, NullCheck nullCheck) throws Throwable {

int position = nullCheck.position();

Object[] objects = joinPoint.getArgs();

if (objects.length > 0 && position < objects.length) {

if (!ObjectUtils.isEmpty(objects[position])) {

joinPoint.proceed();

}

}

}

}

  1. 使用方法

public void nullCheck(View view) {

getString(“Tommy”, null);

}

@NullCheck(position = 1)

private void getString(String name, String country) {

Log.i(TAG, “this is after nullcheck input”);

}

总结

找工作是个很辛苦的事情,而且一般周期都比较长,有时候既看个人技术,也看运气。第一次找工作,最后的结果虽然不尽如人意,不过收获远比offer大。接下来就是针对自己的不足,好好努力了。

最后为了节约大家的时间,我把我学习所用的资料和面试遇到的问题和答案都整理成了PDF文档

喜欢文章的话请关注、点赞、转发 谢谢!

[外链图片转存中…(img-stR93jmP-1721109983829)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值