Use AspectJX, the open source of Hujiang
Github.com/HujiangTech…
Monitor the ImageLoader
Find the entry point: the imageloader.displayImage method
/** * Each overloaded method of ImageLoader will eventually call the displayImage method * so use AdpectJ to go into that method and replace the ImageLoadingListener with our own listener */
@Aspect
public class ImageAspectj {
public static final String TAG = "ImageAspectj";
// Total number of arguments
private static final int ARG_LEN = 5;
/ / imageLoadingListener serial number
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();
// The parameter is null, or the length is not 5- just a boundary judgment; Non-spatial activities do not replace ImageLoadingListener when loading an image
if (TextUtils.isEmpty(uri) || args == null|| args.length ! = ARG_LEN || ! GSConstant.inGsActivity) { point.proceed(); }else {
VLog.d(TAG, "imageLoaderDisplayImage : " + uri);
/ / replace ImageLoadingListener
// Monitor logic
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()); }}}Copy the code
Monitor the Glide
Entry point: singlerequest.obtain ()
/** * Glide's SingleRequest is responsible for packaging requests, and obtains both the image address and the list of listeners in the obtain() method * so we used AspectJ to access that method and add our own listeners to listen for the image loading process */
@Aspect
public class GlideAspectj {
private static final String TAG = "GlideAspectj";
// Total number of arguments
private static final int ARG_LEN = 15;
//requestListeners are the 11th parameter, position 10 in the array
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,targetListene r,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) {}/** * If the PointCut method returns a value, the result should also be returned Around
@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 can be Drawable, Bitmap, GifDecoder, WebpDecoder, etc., which only deals with web URLS and URIs
RequestListener li = null;
if (model instanceof String || model instanceof Uri) {
// Add the monitoring logic here
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 {
// Avoid repeated additions
Iterator<RequestListener> it = requestListeners.iterator();
while (it.hasNext()) {
RequestListener tmp = it.next();
if (tmp instanceof GlideImageLoadListenerProxy) {
it.remove();
}
}
}
requestListeners.add(li);
Add our listeners to the requestListeners
args[REQ_LI_INDEX] = requestListeners;
}
returnpoint.proceed(args); }}catch (Throwable throwable) {
VLog.e(TAG, "obtainRequest err : " + throwable.getMessage());
}
return null; }}Copy the code