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