前言
切面編程一直是一個熱點的話題,這篇文章講講一個第三方aop庫在android上的應用。第三方AOP庫官網網址在MainActivity類的頭部已經說明
這章涉及到以下內容:
- aop庫的配置
- aop導入問題解決
- aop的使用
- aop混淆
- 項目結構圖和效果圖
一. aop庫的配置
在你的porject的build.gradle中做以下配置:
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0'
//AOP切面編程依賴
classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:1.1.1'
classpath 'org.aspectj:aspectjtools:1.8.13'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
在 app module 的buildle.gradle中做如下配置:
//AOP切面編程依賴
compile 'com.safframework:saf-aop:1.2.0'
//rxjava2.x
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.0'
//AOP切面編程Cache依賴
implementation 'com.safframework:saf-cache:1.1.0'
implementation 'tony-common:tony-common-utils:1.2.4'
//AOP切面編程Log依賴
implementation 'com.safframework.log:saf-log:1.5.0'
//AOP切面編程AppPrefs依賴
implementation 'com.safframework.injectview:saf-injectview:1.0.0'
annotationProcessor 'com.safframework.injectview:saf-injectview-compiler:1.0.0'
需要注意的是,AOP庫使用的時候,也要添加RxJava2.X的引用。
二. aop導入問題解決
在導入切面編程庫依賴的時候,可能會出現如下問題:
Error:Execution failed for task ':app:transformClassesWithExtractJarsForDebug'.
> Unexpected scopes found in folder 'C:\my_demo_test\TestDemo\app\build\intermediates\transforms\AspectTransform\debug'.
Required: SUB_PROJECTS. Found:
EXTERNAL_LIBRARIES, PROJECT, SUB_PROJECTS
解決方案如下:
造成上述問題是由於as版本,需將Android studio的instant run關閉。具體如下:
Settings → Build, Execution, Deployment → Instant Run and uncheck Enable Instant Run.
配圖如下:
三. aop的使用
AOP涉及的注解有以下幾個:
下面對各注解依次講解:
3.1 Async異步注解
使用類似如下:
@Async
private void AsyncTest(){
LogUtil.e("====當前線程===="+Thread.currentThread().getId());
LogUtil.e("====主線程===="+ Looper.getMainLooper().getThread().getId());
}
在主線程中調用 AsyncTest 方法,會發現其運行在一個不同於主線程的子線程中。
3.2 Cacheable緩存注解
存儲數據如下:
@Cacheable(key = "name")
private String putCache(){
return "我是誰";
}
獲取緩存數據:
private String getCache(){
Cache cache=Cache.get(CacheActivity.this);
//Cache的存取方式就是Acache,只不過存儲地址改成了緩存而已
String name=cache.getString("name");
return name;
}
3.3 Log注解
你可以類似這樣使用:
@LogMethod
private void log1(){
LogUtil.e("=====log1======");
}
@LogMethod
private String log2(String s){
LogUtil.e("=====log2======"+s);
return s;
}
然后在需要用到的地方直接調用 log1 和 log2 方法就可以打印log了,它最大的好處是不會在代碼中穿插各種 Log代碼。
3.4 Hook注解
使用范例:
@HookMethod(beforeMethod = "before",afterMethod = "after")
private void getMachine(){
LogUtil.e("======getMachine=====");
}
private void before(){
LogUtil.e("====開始時間=======");
}
private void after(){
LogUtil.e("====結束時間=======");
}
然后在調用getMachine方法的時候,你會收到這樣的log
這個可以用來監測一個方法執行的用時,當然,你在聲明Hook注解的時候必須包含 beforeMethod,afterMethod中的一個或同時具有,若不聲明,則Hook使用無效
3.5 Prefs注解
類似手機上的文件存儲,存值你可以這樣操作:
@Prefs(key = "key")
private String putPrefs(){
return "大家好";
}
取值是這樣的:
private String getPrefs(){
AppPrefs appPrefs=AppPrefs.get(PrefsActivity.this);
String key=appPrefs.getString("key",null);
return key;
}
3.6 safe注解
保證代碼執行安全的,若不想代碼拋出異常,你可以這樣處理:
@Safe
private void testStringLength(){
String msg=null;
int length=msg.length();
}
這樣,你在調用 testStringLength 方法的時候就不會報錯了。
3.7 Trace注解
可以用來監測方法執行時長,使用時類似這樣:
@Trace
private void testTrace(){
Observable.create(new ObservableOnSubscribe<String>() {
@Trace
@Override
public void subscribe(@NonNull ObservableEmitter<String> e) throws Exception {
e.onNext("111");
}
}).subscribe(new Consumer<String>() {
@Trace
@Override
public void accept(@NonNull String str) throws Exception {
}
});
}
調用 testTrace 方法之后,在log 的 i 級別中,你可以看到這樣的log
這里,我們就可以很清楚的看到每個方法的執行時間了。
四. 混淆
混淆的話,可以這樣處理
-keep class com.safframework.aop.** { *; }
五. 項目結構圖和效果圖
項目結構圖
效果圖
AOP切面編程在android上的應用
注:本文著作權歸作者,由demo大師代發,拒絕轉載,轉載需要作者授權