Android-Universal-Image-Loader异步加载图片框架学习

GitHub下载地址  https://github.com/nostra13/Android-Universal-Image-Loader

先来看一下Android-Universal-Image-Loader框架的用法;

1、初始化ImageLoaderConfiguration(全局的,在整个application中初始化configuration,配置缓存、加载线程等)、

            ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
                    getApplicationContext())
                    .threadPriority(Thread.NORM_PRIORITY - 2)// 设置线程的优先级
                    .denyCacheImageMultipleSizesInMemory()// 当同一个Uri获取不同大小的图片,缓存到内存时,只缓存一个。默认会缓存多个不同的大小的相同图片
                    .discCacheFileNameGenerator(new Md5FileNameGenerator())// 设置缓存文件的名字
                    .discCacheFileCount(60)// 缓存文件的最大个数
                    .tasksProcessingOrder(QueueProcessingType.LIFO)// 设置图片下载和显示的工作队列排序
                    .build();

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

3、创建图片显示选项:DisplayImageOptions options(根据不同的加载图片显示不同而构造不同的选项,主要配置图片加载过程中显示配置,缓存,显示动画);

            DisplayImageOptions options;
            options = new DisplayImageOptions.Builder()
                    .showStubImage(R.drawable.ic_launcher)// 设置图片在下载期间显示的图片
                    .showImageForEmptyUri(R.drawable.ic_launcher)// 设置图片Uri为空或是错误的时候显示的图片
                    .showImageOnFail(R.drawable.ic_launcher)// 设置图片加载/解码过程中错误时候显示的图片
                    .cacheInMemory(true)// 是否緩存都內存中
                    .cacheOnDisc(true)// 是否緩存到sd卡上
                    .displayer(new RoundedBitmapDisplayer(20)).build();

 4、通过ImageLoader显示图片

            // ImageLoader
            ImageLoader imageLoader = ImageLoader.getInstance();
            // 第一个参数是uri,第二个参数是显示图片的imageView,第三个参数是刚刚构造的图片显示选项,第四个参数是加载的回调方法,displayImage有很多重载方法这中介其中一种;
            imageLoader.displayImage(imageUrls[position], holder.image, options, loadingListener)

要学习更详细使用方法,官方的demo直接在上面链接里面有下载;

嘿嘿,开始觉得上面这用法看起来是有点多,且感觉有点麻烦,但仔细研究你会发现它的功能之强大,从设置加载线程优先级别、图片缓存、图片显示包括显示动画等都在考虑在其中,它还有非常好的扩展性,用户可以根据需求配置各种不同的显示效果、加载动画等,综合来看设计是很巧妙的,下面来体会一下这个开源框架的强大设计:

 ----------------------------------------------------分割线------------------------------------------------------------------------

框架特点:

1、多线程的图像加载(线程池的大小,HTTP选项纱、线程控件等);

2、能够很好的监听加载过程;

3、图片显示配置接口(动画,圆角可扩展);

4、内存和磁盘高速缓存;

5、扩展性强,研发人员只需要根据需求实现它提供的各种接口即可;

框架里面使用最多的是建造者模式与策略模式,要从整个包结构开始看起才能更好的熟悉框架设计,才能更好的扩展它使之与自己工程融为一体; 看图,下图为整个开源框架的包结构:

啧啧,这里就不详叙了,框架里面命名很透彻,基本见名知意,它总共分为几大模块:

1、缓存模块; 下图为缓存模块包结构图:

主要分为disc和memory,这主要是磁盘缓存跟内存缓存管理,哈,咋看介么多类,其实大部分是官方提供给我们的策略实现,这里主要用的是策略模式,来分析一下这个包结构: 其实这里我们只要关注两个类,分别是disc和memory下面的DiscCacheAware、MemoryCacheAwarer这两个接口,它提供给了我们外部调用所需要的接口,外部也是直接使用这两个接口,而impl里面则是对这两个类的实现,将接口的行为方法进行不同的策略实现即真正执行的代码; 而我们需要使用的时候,只需要在配置ImageLoaderConfiguration的时候,根据需要配置对应的DiscCacheAware、MemoryCacheAwarer的子类实现即可;

这样做即结构清晰,而且当我们有自己的需求的时候,我们只需要继承这两个接口,定义自己的策略行为即可,不需要修改任何代码逻辑;

2、解码模块: 下图为解码模块包结构图:

看似简单,姑且就当做一个模块吧,结构跟缓存模块类似,我们主要关注ImageDecoder接口,它只有一个方法Bitmap decode(ImageDecodingInfo imageDecodingInfo),其意根据imageDecodingInfo提供给他的解码信息,进行解码,得到我们需要的bitmap;这里应该就明白这个模块的功能了吧!

官方只提供给了我们一个实现类即BaseImageDecoder,这里实现细节就不记录了。 3、显示模块: 下图为显示模块包结构图:

额,多么熟悉的结构,只需要看一个接口BitmapDisplayer,里面只有一个方法display,即整个模块目的只有一个,显示图片,至于如何显示,官方也提供给了我们几种行为策略:FadeInBitmapDisplayer(渐变显示)、RoundedBitmapDisplayer(图片圆角显示)、RoundedVignetteBitmapDisplayer(没玩过,意思是装饰圆角么,嘿嘿)! 当然这只是一点点,具体你要怎么显示,当然是天高任你飞了,只要实现BitmapDisplayer这个接口,就行了。

4、下载模块:

见图:

结构再也不陌生了,啧啧,此模块核心接口ImageDownloader,图片下载,这个接口里面定义了一个内部枚举类Scheme,不得不被如此强大的功能折服了: Scheme代码:

public enum Scheme {
        HTTP("http"), HTTPS("https"), FILE("file"), CONTENT("content"), ASSETS("assets"), DRAWABLE("drawable"), UNKNOWN("");

        private String scheme;
        private String uriPrefix;

        Scheme(String scheme) {
            this.scheme = scheme;
            uriPrefix = scheme + "://";
        }

        /**
         * Defines scheme of incoming URI
         *
         * @param uri URI for scheme detection
         * @return Scheme of incoming URI
         */
        public static Scheme ofUri(String uri) {
            if (uri != null) {
                for (Scheme s : values()) {
                    if (s.belongsTo(uri)) {
                        return s;
                    }
                }
            }
            return UNKNOWN;
        }

        private boolean belongsTo(String uri) {
            return uri.toLowerCase(Locale.US).startsWith(uriPrefix);
        }

        /** Appends scheme to incoming path */
        public String wrap(String path) {
            return uriPrefix + path;
        }

        /** Removed scheme part ("scheme://") from incoming URI */
        public String crop(String uri) {
            if (!belongsTo(uri)) {
                throw new IllegalArgumentException(String.format("URI [%1$s] doesn't have expected scheme [%2$s]", uri, scheme));
            }
            return uri.substring(uriPrefix.length());
        }
    }

Scheme定义了支持的下载图片地址协议,包括content,assets,drawable下的图片都可以做为uri来下载,通过将assets,drawable地址前面加上协议头,来统一管理图片源,着实高;并且给出了判断是否是支持类型的各种方法;

整个显示流程就是这样:下载-->缓存-->解码-->显示,生生不息啊。

5、listener包,这里仅仅是提供给我们了各样的回调,通过这里,我们大致能看到这个框架能让我们做什么,能否实现我们的需求,当然,你够熟悉它,你也可以根据需求添加自己的回调;

6、util包,工具类包!

上面几个模块的设计都是可扩展的,可以在不修改整体代码的情况下通过实现不同的策略行为达到我们的需求。一个好的框架既有强大的功能,又有良好的结构性与扩展性;

啧,怎么越看越空虚,想想自己之前写的图片下载工具,考虑的方面与功能简直弱爆了!

框架学习比较粗糙,欢迎大神留言交流!

原文地址:https://www.cnblogs.com/PDW-Android/p/3640054.html