【Android框架】Android-universal-image-loader源码阅读(一)

来源:互联网 发布:r软件 编辑:程序博客网 时间:2024/05/01 11:48

图片加载是个非常常见的APP功能,而如今框架横行,在图片加载方面出现了很多图片加载框架:Android-universal-image-loader,pacasso,Fresco,Glide等等图片加载框架。今天我们单独研究下Android-univeral-image-loader图片加载框架。Android-universal-image-loader在很多APP中有使用,今天开始解读下源码,分析它的原理,讲讲自己的浅见。


先来看看Android-universal-image-loader图片加载框架的组成结构:这里写图片描述
主要有三部分组成,cache缓存,core核心加载部分,utils工具类部分。
下面来一步步抽丝剥茧。
这里写图片描述

简单的讲就是 ImageLoader 收到加载及显示图片的任务,并将它交给 ImageLoaderEngine , ImageLoaderEngine 分发任务到具体线程池去执行,任务通过 Cache 及 ImageDownloader 获取图片,中间可能经过 BitmapProcessor 和 ImageDecoder 处理,最终转换为 Bitmap 交给 BitmapDisplayer 在 ImageAware 中显示。

先看简单的imageView加载指定url路径下的网络图片:

ImageLoader imageLoader = ImageLoader.getInstance(); //获得单例//加载到imageView中展示imageLoader.displayImage(imageUri, imageView);

调用displayImage(imageUri,imageView);
然后是displayImage(uri, imageAware, options, null, listener,progressListener);
最终调用:

public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options,            ImageSize targetSize, ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {        checkConfiguration();        if (imageAware == null) {            throw new IllegalArgumentException(ERROR_WRONG_ARGUMENTS);        }        if (listener == null) {            listener = defaultListener;        }        if (options == null) {            options = configuration.defaultDisplayImageOptions;        }        if (TextUtils.isEmpty(uri)) {            engine.cancelDisplayTaskFor(imageAware);            listener.onLoadingStarted(uri, imageAware.getWrappedView());            if (options.shouldShowImageForEmptyUri()) {                imageAware.setImageDrawable(options.getImageForEmptyUri(configuration.resources));            } else {                imageAware.setImageDrawable(null);            }            listener.onLoadingComplete(uri, imageAware.getWrappedView(), null);            return;        }        if (targetSize == null) {            targetSize = ImageSizeUtils.defineTargetSizeForView(imageAware, configuration.getMaxImageSize());        }        String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize);        engine.prepareDisplayTaskFor(imageAware, memoryCacheKey);        listener.onLoadingStarted(uri, imageAware.getWrappedView());        Bitmap bmp = configuration.memoryCache.get(memoryCacheKey);        if (bmp != null && !bmp.isRecycled()) {            L.d(LOG_LOAD_IMAGE_FROM_MEMORY_CACHE, memoryCacheKey);            if (options.shouldPostProcess()) {                ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey,                        options, listener, progressListener, engine.getLockForUri(uri));                ProcessAndDisplayImageTask displayTask = new ProcessAndDisplayImageTask(engine, bmp, imageLoadingInfo,                        defineHandler(options));                if (options.isSyncLoading()) {                    displayTask.run();                } else {                    engine.submit(displayTask);                }            } else {                options.getDisplayer().display(bmp, imageAware, LoadedFrom.MEMORY_CACHE);                listener.onLoadingComplete(uri, imageAware.getWrappedView(), bmp);            }        } else {            if (options.shouldShowImageOnLoading()) {                imageAware.setImageDrawable(options.getImageOnLoading(configuration.resources));            } else if (options.isResetViewBeforeLoading()) {                imageAware.setImageDrawable(null);            }            ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey,                    options, listener, progressListener, engine.getLockForUri(uri));            LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(engine, imageLoadingInfo,                    defineHandler(options));            if (options.isSyncLoading()) {                displayTask.run();            } else {                engine.submit(displayTask);            }        }    }

以上代码有几个值得注意的地方:`

String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize);`//这里是对uri及图片大小生成一个key,在之前的DiskLruCache博客中有提及到

bmp.isRecycled()在很多对象释放的时候需要注意,bmp对象若不释放,最终会造成内存泄漏的结果。

Bitmap bmp = configuration.memoryCache.get(memoryCacheKey);。。。。 !bmp.isRecycled()

需要了解的是ImageLoaderEngine对象

ImageLoaderEngine engine;。。。//ImageView的Id对应图片的Keyengine.prepareDisplayTaskFor(imageAware, memoryCacheKey);
//从内存中获取图片展示options.getDisplayer().display(bmp, imageAware, LoadedFrom.MEMORY_CACHE);                listener.onLoadingComplete(uri, imageAware.getWrappedView(), bmp);

下面看看loadImage(String uri, ImageSize targetImageSize, DisplayImageOptions options,ImageLoadingListener listener, ImageLoadingProgressListener progressListener)

//检测Configuration是否为空checkConfiguration();        if (targetImageSize == null) {            targetImageSize = configuration.getMaxImageSize();        }        if (options == null) {            options = configuration.defaultDisplayImageOptions;        }        //封装imageView呈现所需 url路径,size图片大小,呈现方式        NonViewAware imageAware = new NonViewAware(uri, targetImageSize, ViewScaleType.CROP);//CROP是图片的呈现方式        displayImage(uri, imageAware, options, listener, progressListener);//最后展示
1 0