使用沪江开源的aspectjx
监控ImageLoader
找到切入点:ImageLoader.displayImage
方法
/**
* ImageLoader的各个重载方法最终都会调用displayImage方法
* 所以使用AdpectJ切入该方法,将ImageLoadingListener替换为我们自己的监听器
*/
@Aspect
public class ImageAspectj {
public static final String TAG = "ImageAspectj";
//总共的参数个数
private static final int ARG_LEN = 5;
//imageLoadingListener的序号
private static final int REQ_LI_INDEX = 3;
@Pointcut("execution(* com.vivo.imageloader.core.ImageLoader.displayImage(" +
"java.lang.String," +
"com.vivo.imageloader.core.imageaware.ImageAware," +
"com.vivo.imageloader.core.DisplayImageOptions," +
"com.vivo.imageloader.core.listener.ImageLoadingListener," +
"com.vivo.imageloader.core.listener.ImageLoadingProgressListener))" +
"&& args(uri, imageAware,displayImageOptions,imageLoadingListener,progressListener)")
public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions displayImageOptions,
ImageLoadingListener imageLoadingListener, ImageLoadingProgressListener progressListener) {
}
@Around(value = "displayImage(uri, imageAware, displayImageOptions, imageLoadingListener, progressListener)",
argNames = "uri, imageAware, displayImageOptions,imageLoadingListener,progressListener")
public void imageLoaderDisplayImage(ProceedingJoinPoint point, String uri, ImageAware imageAware, DisplayImageOptions displayImageOptions,
ImageLoadingListener imageLoadingListener, ImageLoadingProgressListener progressListener) {
try {
Object[] args = point.getArgs();
//参数为空,或者长度非5-只是边界判断;非空间的activity加载图片时不替换ImageLoadingListener
if (TextUtils.isEmpty(uri) || args == null || args.length != ARG_LEN || !GSConstant.inGsActivity) {
point.proceed();
} else {
VLog.d(TAG, "imageLoaderDisplayImage : " + uri);
//替换ImageLoadingListener
//监控逻辑,自己完善
args[REQ_LI_INDEX] = new ImageLoadingListener(){
@Override
void onLoadingStarted(String var1, View var2);
@Override
void onLoadingFailed(String var1, View var2, FailReason var3);
@Override
void onLoadingComplete(String var1, View var2, Bitmap var3);
@Override
void onLoadingCancelled(String var1, View var2);
};
point.proceed(args);
}
} catch (Throwable throwable) {
VLog.d(TAG, throwable.toString());
}
}
}
监控Glide
切入点:SingleRequest.obtain()
/**
* Glide的SingleRequest负责包装请求,在obtain()方法中能同时获取到图片地址以及监听器列表
* 所以使用AspectJ切入该方法,增加我们自己的监听器,用来监听图片加载过程
*/
@Aspect
public class GlideAspectj {
private static final String TAG = "GlideAspectj";
//总共的参数个数
private static final int ARG_LEN = 15;
//requestListeners是第11个参数,数组中的位置为10
private static final int REQ_LI_INDEX = 10;
@Pointcut("execution(* com.bumptech.glide.request.SingleRequest.obtain(" +
"android.content.Context," +
"com.bumptech.glide.GlideContext," +
"Object," +
"java.lang.Class<Object+>," +
"com.bumptech.glide.request.BaseRequestOptions<?>," +
"int," +
"int," +
"com.bumptech.glide.Priority," +
"com.bumptech.glide.request.target.Target<Object+>," +
"com.bumptech.glide.request.RequestListener<Object+>," +
"java.util.List+," +
"..))" +
"&& args(context,glideContext,model,transcodeClass,requestOptions,overrideWidth,overrideHeight,priority,target,targetListener,requestListeners,..)")
public void singleRequestObtain(Context context,
GlideContext glideContext,
Object model,
Class transcodeClass,
BaseRequestOptions<?> requestOptions,
int overrideWidth,
int overrideHeight,
Priority priority,
Target target,
RequestListener targetListener,
List<RequestListener> requestListeners) {
}
/**
* PointCut的方法如果有返回值,则Around时也需要返回结果,只需要声明为Object即可
*/
@Around(value = "singleRequestObtain(" +
"context," +
"glideContext," +
"model," +
"transcodeClass," +
"requestOptions," +
"overrideWidth," +
"overrideHeight," +
"priority," +
"target," +
"targetListener," +
"requestListeners" +
")",
argNames = "context," +
"glideContext," +
"model," +
"transcodeClass," +
"requestOptions," +
"overrideWidth," +
"overrideHeight," +
"priority," +
"target," +
"targetListener," +
"requestListeners")
public Object obtainRequest(ProceedingJoinPoint point,
Context context,
GlideContext glideContext,
Object model,
Class transcodeClass,
BaseRequestOptions<?> requestOptions,
int overrideWidth,
int overrideHeight,
Priority priority,
Target target,
RequestListener targetListener,
List<RequestListener> requestListeners) {
try {
Object[] args = point.getArgs();
if (model == null || args == null || args.length != ARG_LEN || !GSConstant.inGsActivity) {
return point.proceed();
} else {
VLog.d(TAG, "obtainRequest :" + model);
//model可能是Drawable,Bitmap,GifDecoder,WebpDecoder等,只处理网络url和uri这两种类型
RequestListener li = null;
if (model instanceof String || model instanceof Uri) {
//监控逻辑在此处添加
li = new RequestListener() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(Object resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) {
return false;
}
};
}
if (li != null) {
if (requestListeners == null) {
requestListeners = new ArrayList<>();
} else {
//避免重复添加
Iterator<RequestListener> it = requestListeners.iterator();
while (it.hasNext()) {
RequestListener tmp = it.next();
if (tmp instanceof GlideImageLoadListenerProxy) {
it.remove();
}
}
}
requestListeners.add(li);
//向requestListeners添加我们的监听器
args[REQ_LI_INDEX] = requestListeners;
}
return point.proceed(args);
}
} catch (Throwable throwable) {
VLog.e(TAG, "obtainRequest err : " + throwable.getMessage());
}
return null;
}
}