ImageLoader解析

        今天写一下关于ImageLoader的文章,看下图:


        最终会调用displayImage方法的源码是:

public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options, ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {
    this.checkConfiguration();
    if(imageAware == null) {
        throw new IllegalArgumentException("Wrong arguments were passed to displayImage() method (ImageView reference must not be null)");
    } else {
        if(listener == null) {
            listener = this.defaultListener;
        }

        if(options == null) {
            options = this.configuration.defaultDisplayImageOptions;
        }

        if(TextUtils.isEmpty(uri)) {
            this.engine.cancelDisplayTaskFor(imageAware);
            listener.onLoadingStarted(uri, imageAware.getWrappedView());
            if(options.shouldShowImageForEmptyUri()) {
                imageAware.setImageDrawable(options.getImageForEmptyUri(this.configuration.resources));
            } else {
                imageAware.setImageDrawable((Drawable)null);
            }

            listener.onLoadingComplete(uri, imageAware.getWrappedView(), (Bitmap)null);
        } else {
            ImageSize targetSize = ImageSizeUtils.defineTargetSizeForView(imageAware, this.configuration.getMaxImageSize());
            String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize);
            this.engine.prepareDisplayTaskFor(imageAware, memoryCacheKey);
            listener.onLoadingStarted(uri, imageAware.getWrappedView());
            //这里先尝试从内存缓存(ImageLoader有内存,硬盘缓存)中取图片
            Bitmap bmp = this.configuration.memoryCache.get(memoryCacheKey);
            ImageLoadingInfo imageLoadingInfo;
            //这里是拿到了图片
            if(bmp != null && !bmp.isRecycled()) {
                L.d("Load image from memory cache [%s]", new Object[]{memoryCacheKey});
            //判断图片需不需要处理,如果需要处理
            if(options.shouldPostProcess()) {
                    imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey, options, listener, progressListener, this.engine.getLockForUri(uri));
                    //创建一个处理并显示的线程任务 并添加到 taskExecutorForCachedImages 线程池里面
                    ProcessAndDisplayImageTask displayTask1 = new ProcessAndDisplayImageTask(this.engine, bmp, imageLoadingInfo, defineHandler(options));
                    if(options.isSyncLoading()) {
                        displayTask1.run();
                    } else {
                        //添加到taskExecutorForCachedImages 线程池
                        this.engine.submit(displayTask1);
                    }
                } else {
                    //不需要处理就直接显示
                    options.getDisplayer().display(bmp, imageAware, LoadedFrom.MEMORY_CACHE);
                    listener.onLoadingComplete(uri, imageAware.getWrappedView(), bmp);
                }
            } else {
                if(options.shouldShowImageOnLoading()) {
                    imageAware.setImageDrawable(options.getImageOnLoading(this.configuration.resources));
                } else if(options.isResetViewBeforeLoading()) {
                    imageAware.setImageDrawable((Drawable)null);
                }

                imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey, options, listener, progressListener, this.engine.getLockForUri(uri));
                //没有在内存中,那就创建一个下载并显示的线程任务,添加到 taskDistributor 线程任务中,这里需要注意的是这个是添加到分发线程池里面,不是直接去
                //下载的
                LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(this.engine, imageLoadingInfo, defineHandler(options));
                if(options.isSyncLoading()) {
                    displayTask.run();
                } else {
                    this.engine.submit(displayTask);
                }
            }

        }
    }
}

    现在看 this.engine.submit(displayTask) 函数(图片没有在内存中的,也就是上面红色的部分,内存中有的要么直接显示,要么直接添加到
taskExecutorForCachedImages里面,不需要分发)的源码:

void submit(final LoadAndDisplayImageTask task) {
    //没有直接去下载,而是先根据情况分发事件
    this.taskDistributor.execute(new Runnable() {
        public void run() {
            File image = ImageLoaderEngine.this.configuration.diskCache.get(task.getLoadingUri());
            boolean isImageCachedOnDisk = image != null && image.exists();
            ImageLoaderEngine.this.initExecutorsIfNeed();
            //这里是在硬盘缓存中存在的图片,直接添加到 taskExecutorForCachedImages 线程池,也是属于从缓存中取的,那为什么没有直接取出来而要另起线程呢?
            //那是因为硬盘读数据比内存读数据慢,所以放在线程里
            if(isImageCachedOnDisk) {
                ImageLoaderEngine.this.taskExecutorForCachedImages.execute(task);
            } else {
                //因为硬盘上也没有,只能放在从网络下载的线程池里面
                ImageLoaderEngine.this.taskExecutor.execute(task);
            }

        }
    });
}

    submit函数中不管是放在那个线程池中,都会执行 LoadAndDisplayImageTask 的 run 函数,至于为什么分线程池呢?可能是想更好的利用系统资源吧,这个以后再研究,
如果有不对的地方还请高手给我指点,一起学习一起进步。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值