美文网首页
带你细细品读Android-Universal-Image-Lo

带你细细品读Android-Universal-Image-Lo

作者: WHOKNOWME | 来源:发表于2016-11-10 10:57 被阅读107次

首先,本人非常钦佩和仰慕 Android-Universal-Image-Loader 的作者:Sergey Tarasevich

关于风:
自己从没有写过类似源码品读这样的博客,瞬间觉得有点压力和激动。一方面是这么一个写的如此精妙和伟大的库,让我等小辈去评头论足,实在显得不够尊重。另一方面则是,如此一个广泛使用的,从2011年就面世的库,一旦自己能力不够,导致品读的不到位,抑或是误导了广大的用户,这个责任就难当了。所以此时此刻,自己的心情是忐忑的,是惶恐的,是复杂和纠结的。

在此,先感谢 Sergey Tarasevich,再感谢各位读者。

品读这么伟大的库,一篇博客是不够的,那么两篇?也是不够的!废话少说!
首先抛出一个问题:如何阅读一个开源库?从什么地方入手?
我的思路是从如何使用方面入手,比如Universal-Image-Loader库的使用方式:

1.在App的入口处全局配置ImageLoader.

public static void initImageLoader(Context context) {
    // This configuration tuning is custom. You can tune every option, you may tune some of them,
    // or you can create default configuration by
    //  ImageLoaderConfiguration.createDefault(this);
    // method.
    ImageLoaderConfiguration.Builder config = new 
        ImageLoaderConfiguration.Builder(context);
    config.threadPriority(Thread.NORM_PRIORITY - 2);
    config.denyCacheImageMultipleSizesInMemory();//拒绝在内存中缓存2种size的图片策略
    config.diskCacheFileNameGenerator(new Md5FileNameGenerator());//磁盘缓存文件名的产生方案,你选择采用其他策略
    config.diskCacheSize(50 * 1024 * 1024); // 磁盘缓存大小 50 MiB
    config.tasksProcessingOrder(QueueProcessingType.LIFO);//配置任务队列的执行方式
    config.writeDebugLogs(); // Remove for release app

    // Initialize ImageLoader with configuration.
    ImageLoader.getInstance().init(config.build());
}

ImageLoader的可配置的信息非常丰富,上面所列的只是一部分。这种全局配置的策略是很值推广,ImageLoader本身有自己的默认策略,但是默认毕竟是默认的,无法满足不同业务的需求。所以我们在开发一款工具类开源库的时候,可以将这种插件式的设计思想引入到你的库当中。

2.图片显示调用:ImageLoader.getInstance().displayImage()

这个方法的背后隐藏了这个库的所有秘密。ImageLoader.getInstance()采用单例的设计模式:

    /** Returns singleton class instance */
    public static ImageLoader getInstance() {
        if (instance == null) {
            synchronized (ImageLoader.class) {
                if (instance == null) {
                    instance = new ImageLoader();
                }
            }
        }
        return instance;
    }

双重检查的单例模式,单例模式的实现方法之一,保证全局只有一个实例存在,节约了频繁创建和销毁对象时系统资源的开销,提高了我们系统的性能。
获取ImageLoader的实例之后,就开始调用displayImage()方法去显示图片了,从源码中我们可以看到,在ImageLoader这个类中多次重载了displayImage()的方法。但是核心的方法往往只有一个,而且这个核心的方法也非常有意思,我们一起来看看。

public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options,
            ImageSize targetSize, ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {
        checkConfiguration();
        
        ... //此处省略部分源码
        
        if (TextUtils.isEmpty(uri)) {//过滤url为空的情况
            engine.cancelDisplayTaskFor(imageAware);
            listener.onLoadingStarted(uri, imageAware.getWrappedView());
            if (options.shouldShowImageForEmptyUri()) {
                imageAware.setImageDrawable(options.getImageForEmptyUri(configuration.resources));//显示你配置url为空时显示的图片
            } 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);//根据图片url生产一个键
        //将imageView的hashcode与url产生的键做一个map映射
        engine.prepareDisplayTaskFor(imageAware, memoryCacheKey);

        listener.onLoadingStarted(uri, imageAware.getWrappedView());
        //获取内存中缓存的bitmap
        Bitmap bmp = configuration.memoryCache.get(memoryCacheKey);
        if (bmp != null && !bmp.isRecycled()) {//如果内存中存在bmp
            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 {
            ... //此处省略部分源码
            //下面是处理图片的网络下载或者加载本地磁盘缓存图片的逻辑
            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);
            }
        }
    }

代码有点多,但是写的非常精彩,在这里我不做展开,主要是帮大家屡一下图片的显示逻辑,所有的逻辑都隐藏在代码中。下面是我画的一个流程图

图片加载流程图

流程图画的不是很好,但是可以说明问题。好了,源码再结合流程图应该可以很好的说明了ImageLoader加载图片的主要逻辑。后面的几篇博客我会继续解读ImageLoader源码。会有这么几个方面:

1. ImageLoaderEngine 的源码解读
2. BaseImageDownloader 的源码解读
3. ImageLoader 的内存缓存策略
4. ImageLoader 的磁盘缓存策略
5. ImageLoader 的接口编程思想

有问题欢迎留言!

相关文章

  • 带你细细品读Android-Universal-Image-Lo

    首先,本人非常钦佩和仰慕 Android-Universal-Image-Loader 的作者:Sergey Ta...

  • 细细品读

    节前最后一个周末被约携娃看展听讲解《金石书香沁后人——周叔弢捐献文物与古籍特展》。这个展我11月份篆刻收尾前凑巧看...

  • 值得细细品读!

    别墅豪宅、高档家具、奢侈物件、奢华旅游,稀有器皿、俊男靓女,这些东西像磁铁一样吸引着人们。没有人会想到,物质的攀比...

  • 细细品读(摘录)

    朱光潜:文学作品,一目十行是荒谬的。金宋时期的大文学家元遗山在论文诗里说:“文须字字作,亦要字字读,咀嚼有余味,百...

  • 这些文章值得细细品读

    【闻凉茶馆】这个专题建立有九天时间了。那篇专题投稿文章我一直置顶。 一方面,希望能有更多的朋友能看到,积极投稿。另...

  • 意境超美的诗句,值得细细品读

    今天特意在百度百科上看到这么一段话: 从文学风貌论,七古的典型风格是端正浑厚、庄重典雅,歌行的典型风格则是宛转流动...

  • 夫妻之间的因果(值得细细品读)

    有人说: “树叶沙沙响,必定有风来。” 世间所有的事物,凡有果,都必有因。 夫妻之间的相处,亦是如此。 感情若是甜...

  • 100句名言

    100本名著里提炼的100句名言,都是值得细细品读和收藏的精华!

  • 好女人

    美文品读: 好女人是一本书。闻着,有花清香;听着,有诗韵味;看着,有舞旋律;读着,每天总有新感觉,需要细细品读。好...

  • 蒋勋说唐诗。阅读札记③

    小时仅仅觉得觉得武则天身为女子,却当上了皇帝,万分厉害。长大后,细细品读武则天的传奇故事,却品读出了不一样的味道。...

网友评论

      本文标题:带你细细品读Android-Universal-Image-Lo

      本文链接:https://www.haomeiwen.com/subject/nxvouttx.html