android 开源框架Universal-Image-Loader解析

来源:互联网 发布:遗传算法过程 编辑:程序博客网 时间:2024/04/30 03:08

Android开发中我们会经常遇到图片过多或操作不当造成OOM异常,有时虽然是解决了这个问题但却会影响程序的运行效率,例如:当用户在快速滑动滚动条的过程中,我们程序在仍在艰难的加载服务器端的图片,这样给用户造成了极不好的体验。其实网络上关于图片的异步加载和缓存的讲解很多,但是其实,写一个这方面的程序还是比较麻烦的,要考虑多线程,缓存,内存溢出等很多方面,针对这一光大开发者都会遇到的问题,开源框架ImageLoader便能很好的解决这一问题
1. 功能特性:

  1. 多线程异步加载和显示图片(图片来源于网络、sd卡、assets文件夹,drawable文件夹(不能加载9patch),新增加载视频缩略图)。

  2. 支持二级缓存,即内存缓存(软引用)及本地缓存。

  3. 对加载过程实现监听和事件处理。通过“listener”监视加载的过程,可以暂停加载图片,在经常使用的ListView、GridView中,可以设置滑动时暂停加。载,停止滑动时加载图片(便于节约流量,在一些优化中可以使用)。

  4. 高度可定制化(可以根据自己的需求进行各种配置,如:线程池,图片下载器,内存缓存策略等)。

2. UIL原理:

a.UI:请求数据,使用唯一的Key值索引MemoryCache中的Bitmap。b.内存缓存:缓存搜索,如果能找到Key值对应的Bitmap,则返回数据。否则执行c。c.硬盘存储:使用唯一Key值对应的文件名,检索SDCard上的文件。如果有对应文件,使用BitmapFactory.decode*方法,解码Bitmap并返回数据,同时将数据写入缓存。如果没有对应文件,执行d。d.下载图片:启动异步线程,从数据源下载数据(Web)。e.若下载成功,将数据同时写入硬盘和缓存,并将Bitmap显示在UI中。

这里写图片描述

3. 配置和使用:

  1. 新建一个类继承Application,实现初始化ImageLoader
public class AppContext extends Application {    private static Context mContext;    @Override    public void onCreate() {        super.onCreate();        mContext = this;        initImageLoader();    }    public static Context getAppContext() {        return context;    }    private final static void initImageLoader() {        ImageLoaderConfiguration config = new  ImageLoaderConfiguration.Builder(context)                .defaultDisplayImageOptions(getDefaultDisplayOption())//显示图片的参数,传入自己配置过得DisplayImageOption对象                .memoryCache(new LruMemoryCache(2 * 1024 * 1024)) //缓存策略                  .memoryCacheExtraOptions(480, 800) //即保存的每个缓存文件的最大长宽                  .threadPoolSize(5) //线程池内线程的数量,默认是3                .threadPriority(Thread.NORM_PRIORITY - 2) //当同一个Uri获取不同大小的图片,缓存到内存时,只缓存一个。默认会缓存多个不同的大小的相同图片                .denyCacheImageMultipleSizesInMemory() //拒绝同一个url缓存多个图片                .diskCacheSize(50 * 1024 * 1024) //设置磁盘缓存大小 50M                  .diskCacheFileNameGenerator(new Md5FileNameGenerator()) //将保存的时候的URI名称用MD5 加密                 .imageDownloader(new BaseImageDownloader(this, 5 * 1000, 30 * 1000)) // connectTimeout (5 s), readTimeout (30 s)超时时间                  .tasksProcessingOrder(QueueProcessingType.LIFO)//设置图片下载和显示的工作队列排序                .build();        ImageLoader.getInstance().init(config);    }    private final static DisplayImageOptions getDefaultDisplayOption() {        DisplayImageOptions options = new DisplayImageOptions.Builder()                .showImageForEmptyUri(R.drawable.empty_photo)  // 设置图片Uri为空或是错误的时候显示的图片                .showImageOnFail(R.drawable.empty_photo)     //  设置图片加载或解码过程中发生错误显示的图片                .cacheInMemory(true) // 设置下载的图片是否缓存在内存中                .cacheOnDisk(true) // 设置下载的图片是否缓存在SD卡中                .showImageOnLoading(R.drawable.empty_photo)                .build();         return options;    }}

2.在清单文件AndroidManifest.xml中的application节点中加入

android:name=".MyApplication"

3.在Activity中使用ImageLoader:

     ImageLoader.getInstance().displayImage(uri, imageView);

清除缓存的方法有:

    ImageLoader.getInstance().clearDiskCache();    ImageLoader.getInstance().clearMemoryCache();

4. Universal-Image-Loader的内存缓存策略:

1.强引用缓存:LruMemoryCache(这个类就是这个开源框架默认的内存缓存类,缓存的是bitmap的强引用)好处:滑动时图片不会容易被清除,体验好;坏处:容易出现OOM2.使用强引用和弱引用相结合的缓存有:UsingFreqLimitedMemoryCache(如果缓存的图片总量超过限定值,先删除使用频率最小的bitmap)LRULimitedMemoryCache(这个也是使用的lru算法,和LruMemoryCache不同的是,他缓存的是bitmap的弱引用)FIFOLimitedMemoryCache(先进先出的缓存策略,当超过设定值,先删除最先加入缓存的bitmap)LargestLimitedMemoryCache(当超过缓存限定值,先删除最大的bitmap对象)LimitedAgeMemoryCache(当 bitmap加入缓存中的时间超过我们设定的值,将其删除)3.只使用弱引用缓存:WeakMemoryCache(这个类缓存bitmap的总大小没有限制,唯一不足的地方就是不稳定,缓存的图片容易被回收掉)好处:对缓存的bitmap总大小无限制;坏处:使得图片不稳定,图片极其容易被回收*注意:不要使用.cacheInMemory();*

5. Universal-Image-Loader的硬盘缓存策略

FileCountLimitedDiscCache(可以设定缓存图片的个数,当超过设定值,删除掉最先加入到硬盘的文件)LimitedAgeDiscCache(设定文件存活的最长时间,当超过这个值,就删除该文件)TotalSizeLimitedDiscCache(设定缓存bitmap的最大值,当超过这个值,删除最先加入到硬盘的文件)UnlimitedDiscCache(这个缓存类没有任何的限制)在ImageLoaderConfiguration中配置了diskCacheSize和diskCacheFileCount,他就使用的是LruDiscCache,否则使用的是UnlimitedDiscCache在最新的源码中还有一个硬盘缓存类可以配置,那就是LimitedAgeDiscCache,可以在ImageLoaderConfiguration.diskCache(...)配置

避免OOM

为了避免OOM,可以修改下面的配置方案:


  • .memoryCacheExtraOptions(480, 800) //即保存的每个缓存文件的最大长宽,大小自行配制

  • .threadPriority(Thread.NORM_PRIORITY - 2) //线程池中线程的个数,一般配置1-5,这里配的是3

  • .memoryCache(new LRULimitedMemoryCache(40*1024*1024)) //改变缓存策略,可以用弱引用

1 0