ImageLoader解析

来源:互联网 发布:office2007激活软件 编辑:程序博客网 时间:2024/06/15 00:18

        今天写一下关于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