企业网站建设珠海,成都网站建设常见问题,asp网站开发移动端,做网站怎么插音频开篇这篇恐怕又是一篇补足网上超9成关于这个领域实际都是错的、用不起来的一个知识点了。网上太多太多教程和案例用的是一个叫hujiang的AOP组件-com.hujiang.aspectjx:gradle-android-plugin-aspectjx。首先这些错的文章我不知道是怎么来的#xff0c;其次那些案例真的运行成功…开篇 这篇恐怕又是一篇补足网上超9成关于这个领域实际都是错的、用不起来的一个知识点了。网上太多太多教程和案例用的是一个叫hujiang的AOP组件-com.hujiang.aspectjx:gradle-android-plugin-aspectjx。 首先这些错的文章我不知道是怎么来的其次那些案例真的运行成功过吗它们用的都是aspectjx功能是为了兼容Kotlin。 还是那句话Java开发和Kotlin还有Flutter开发到底有什么区别整一堆无用功、把框架搞得很复杂、一堆错误的无用的代码混在一起这才是本质。开发了好用什么语言都可以开发出好东西来开发了不好就只剩下了我用的开发语言是最先进的。因此我们坚持使用Java。 扯回来我们继续来看AOP功能在Android中的使用由于Android是Java语言因此它也支持aspectj功能用法和在spring系里使用一模一样的简单。只不过都是被了这个叫com.hujiang.aspectjx:gradle-android-plugin-aspectjx搞了太复杂了甚至有人几天都调不通一个AOP功能。 因此本篇就是交给大家正确的、纯净的、纯真的AOP使用方法。AOP的使用场景 AOP使用场景太多了如拦截方法打印日志特别是APP里有很多activity它要求用户必须登录才可以打开如用户积分、我的历史订单等。对于这些界面我们要求如果用户不登录那么APP自动跳到登录页。 这种操作就是用的AOP功能去实现的。如何使用一个AOP来判断用户打开界面前是否已经登录 一个activity从进入到展示界面在onCreate方法里一般会经历这么几个方法这里的initMain()就是用来展示界面的。我们为了做这个界面在展示前判断用户是否已经登录我们会这么“切”一刀。然后把这个判断用户是否已经登录做成一个和后端交互的API整个是否登录的判断逻辑如下截图动手使用AOP实现 我们假设后台的这个接口如下所示这边用了上一篇讲到的retrofit2okhttp3rxjava。package com.mkyuan.aset.mall.android.login.api;import com.mkyuan.aset.mall.android.login.model.LoginResponseBean;import io.reactivex.Observable;
import okhttp3.RequestBody;
import retrofit2.http.Body;
import retrofit2.http.Header;
import retrofit2.http.POST;public interface LoginAPI {POST(/api/account/checkLoginUT)Observable LoginResponseBean checkLoginUT(Header(ut) String ut);
}所以我们现在开始动手制作我们的AOP了。先引入AOP包 我们这边不会使用网上的已经不维护的、一堆问题的“com.hujiang.aspectjx:gradle-android-plugin-aspectjx”。 请直接使用“org.aspectj:aspectjrt:1.9.6”。为此第一步编程全局build.gradle加入以下语句dependencies {classpath org.aspectj:aspectjtools:1.9.6
}第二步编辑我们的模块级别的build.gradle文件先引入aspectjrt包 implementation org.aspectj:aspectjrt:1.9.6 //引入 aspectj然后再要在同一个build.gradle中加入如下语句//使得aop生效
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main// 获取log打印工具和构建配置
final def log project.logger
final def variants project.android.applicationVariants
variants.all { variant -if (!variant.buildType.isDebuggable()) {// 判断是否debug如果打release把return去掉就可以log.debug(Skipping non-debuggable build type ${variant.buildType.name}.)// return;}// 使aspectj配置生效JavaCompile javaCompile variant.javaCompilejavaCompile.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);//在编译时打印信息如警告、error等等for (IMessage message : handler.getMessages(null, true)) {switch (message.getKind()) {case IMessage.ABORT:case IMessage.ERROR:case IMessage.FAIL:log.error message.message, message.thrownbreak;case IMessage.WARNING:log.warn message.message, message.thrownbreak;case IMessage.INFO:log.info message.message, message.thrownbreak;case IMessage.DEBUG:log.debug message.message, message.thrownbreak;}}}
}加完后的build.gradle长这个样/*** following plugins is the original version*/
/*
plugins {id com.android.application
}
*/
/*** by using aspectj must ad following lines tart*/
apply plugin: com.android.application
//apply plugin: android-aspectjx //暂时注了
/*** by using aspectj must ad following lines tart*/
android {namespace com.mkyuan.aset.mall.androidcompileSdk 32defaultConfig {applicationId com.mkyuan.aset.mall.androidminSdk 27targetSdk 32versionCode 1versionName 1.0testInstrumentationRunner androidx.test.runner.AndroidJUnitRunner}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile(proguard-android-optimize.txt), proguard-rules.pro}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}dataBinding {enabled true}//aspectjx {// exclude **/module-info.class// exclude META-INF.versions.9.module-info// exclude META-INF/versions/9/*.class// exclude com.google, com.squareup, org.apache,com.taobao,com.ut// exclude androidx, com.squareup, com.alipay, org.apache, org.jetbrains.kotlin,// module-info, versions.9//}}dependencies {implementation org.aspectj:aspectjrt:1.9.6 //引入 aspectjimplementation com.github.bumptech.glide:glide:4.11.0annotationProcessor com.github.bumptech.glide:compiler:4.11.0implementation org.aspectj:aspectjrt:1.9.6implementation io.github.youth5201314:banner:2.2.2//com.google.android.material.theme//implementation com.google.android.material:material:version//retrofit2implementation com.squareup.retrofit2:retrofit:2.9.0implementation com.squareup.retrofit2:converter-gson:2.9.0//日志拦截器implementation com.squareup.okhttp3:logging-interceptor:3.10.0implementation com.squareup.retrofit2:adapter-rxjava2:2.4.0//rxjavaimplementation io.reactivex.rxjava2:rxandroid:2.1.1implementation io.reactivex.rxjava2:rxjava:2.2.12//gsonimplementation com.google.code.gson:gson:2.8.7implementation androidx.appcompat:appcompat:1.4.1implementation com.google.android.material:material:1.5.0implementation androidx.constraintlayout:constraintlayout:2.1.3testImplementation junit:junit:4.13.2androidTestImplementation androidx.test.ext:junit:1.1.3androidTestImplementation androidx.test.espresso:espresso-core:3.4.0
}//使得aop生效
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main// 获取log打印工具和构建配置
final def log project.logger
final def variants project.android.applicationVariants
variants.all { variant -if (!variant.buildType.isDebuggable()) {// 判断是否debug如果打release把return去掉就可以log.debug(Skipping non-debuggable build type ${variant.buildType.name}.)// return;}// 使aspectj配置生效JavaCompile javaCompile variant.javaCompilejavaCompile.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);//在编译时打印信息如警告、error等等for (IMessage message : handler.getMessages(null, true)) {switch (message.getKind()) {case IMessage.ABORT:case IMessage.ERROR:case IMessage.FAIL:log.error message.message, message.thrownbreak;case IMessage.WARNING:log.warn message.message, message.thrownbreak;case IMessage.INFO:log.info message.message, message.thrownbreak;case IMessage.DEBUG:log.debug message.message, message.thrownbreak;}}}
}制作AOP相关的代码Login.java-定义一个基于方法切面的annotationpackage com.mkyuan.aset.mall.android.util.aop.login;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;//不需要回调的处理
Target(ElementType.METHOD)
Retention(RetentionPolicy.RUNTIME)
public interface Login {
}
LoginAspect.java -使用Around模式对含有Login的方法进行切面package com.mkyuan.aset.mall.android.util.aop.login;import android.util.Log;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;Aspect
public class LoginAspect {private static final String TAG LoginAspect;Pointcut(execution(com.mkyuan.aset.mall.android.util.aop.login.Login * *(..)))public void executionCheckLogin() {}//不带回调的注解处理Around(executionCheckLogin())public void loginJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {Log.i(TAG, 走进AOP方法);Signature signature joinPoint.getSignature();if (!(signature instanceof MethodSignature)) {throw new RuntimeException(该注解只能用于方法上);}Login login ((MethodSignature) signature).getMethod().getAnnotation(Login.class);if (login null)return;//判断当前是否已经登录LoginManager.isLogin(new LoginCheckCallBack() {Overridepublic void changeValue(boolean loginResult) {if(loginResult) {Log.i(TAG, 用户己登录走入下一步);try {joinPoint.proceed();} catch (Throwable e) {Log.e(TAG,e.getMessage(),e);}}else{//如果未登录去登录页面Log.i(TAG, 用户未登录去登录页面);LoginManager.gotoLoginPage();}}});}
}
LoginManager.java 内含有和后台是否登录接口交互以及判断用户如果已经登录那么继续“走下去-打开界面”否则跳到Login登录界面的逻辑package com.mkyuan.aset.mall.android.util.aop.login;import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;import com.google.gson.Gson;
import com.mkyuan.aset.mall.android.home.MainActivity;
import com.mkyuan.aset.mall.android.login.LoginActivity;
import com.mkyuan.aset.mall.android.login.SmsLoginActivity;
import com.mkyuan.aset.mall.android.login.api.LoginAPI;
import com.mkyuan.aset.mall.android.login.model.LoginResponseBean;
import com.mkyuan.aset.mall.android.network.BaseObserver;
import com.mkyuan.aset.mall.android.network.NetworkApi;
import com.mkyuan.aset.mall.android.util.ContextUtils;
import com.mkyuan.aset.mall.android.util.SharedPreferenceHelper;
import com.mkyuan.aset.mall.android.util.activity.ActivityCollector;import java.util.Map;import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.RequestBody;public class LoginManager {private static final String TAG LoginAspect;public static void isLogin(LoginCheckCallBack loginCheckCallBack) {Context ctx null;try {ctx ContextUtils.getCurApplicationContext();SharedPreferenceHelper spHelper new SharedPreferenceHelper(ctx);MapString, String data spHelper.read();if (data.get(ut) ! null data.get(ut).trim().length() 0) {String utValue data.get(ut);//开始调用okhttp3, retrofit, rxjava框架LoginAPI loginAPI NetworkApi.createService(LoginAPI.class);//loginAPI.checkLoginUT().loginAPI.checkLoginUT(utValue).compose(NetworkApi.applySchedulers(new BaseObserverLoginResponseBean() {Overridepublic void onSuccess(LoginResponseBean loginResponseBean) {Log.i(TAG, new Gson().toJson(loginResponseBean));int returnCode loginResponseBean.getCode();String returnMsg loginResponseBean.getMessage();if (returnCode 0) {//result true;loginCheckCallBack.changeValue(true);Log.i(TAG,get verifiedCode- loginResponseBean.getData());//startActivity(new Intent(SmsLoginActivity.this, MainActivity// .class));} else {loginCheckCallBack.changeValue(false);}}Overridepublic void onFailure(Throwable e) {Log.e(TAG, Network Error: e.toString(), e);loginCheckCallBack.changeValue(false);}}));} else {loginCheckCallBack.changeValue(false);}} catch (Exception e) {Log.e(TAG, isLogin error: e.getMessage());loginCheckCallBack.changeValue(false);}}public static void gotoLoginPage() {Context ctx null;try {ctx ContextUtils.getCurApplicationContext();Intent intent new Intent();intent.setClass(ctx, LoginActivity.class);intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);ctx.startActivity(intent);ActivityCollector.getInstance().quitCurrentProcess(com.mkyuan.aset.mall.android.home.MainActivity);} catch (Exception e) {Log.e(TAG, gotoLoginPage error: e.getMessage(), e);}}
}
使用这个AOP 在MainActivity代码里有一个initMain方法渲染界面的逻辑全部在这个initMain方法里。接着我们来看这个initMain()方法。在方法前我们加入了自定义的“切入点”。效果演示第一次打开APP用户未登录因此直接被跳到了Login界面然后输入手机点获取验证码按提交登录成功。然后关闭APP再次打开APP由于之前用户已经登录过了因此AOP直接会把用户带入到主页结合着我上一篇retrofit2okhttp3rxjava自己不妨动动手试试看吧