Android Universal ImageLoader 缓存图片
项目介绍:
Android上最让人头疼的莫过于从网络获取图片、显示、回收,任何一个环节有问题都可能直接OOM,这个项目或许能帮到你。UniversalImageLoaderforAndroid的目的是为了实现异步的网络图片加载、缓存及显示,支持多线程异步加载。它最初来源于FedorVlasov的项目,且自此之后,经过大规模的重构和改进。
特性列举:
多线程下载图片,图片可以来源于网络,文件系统,项目文件夹assets中以及drawable中等
支持随意的配置ImageLoader,例如线程池,图片下载器,内存缓存策略,硬盘缓存策略,图片显示选项以及其他的一些配置
支持图片的内存缓存,文件系统缓存或者SD卡缓存
支持图片下载过程的监听
根据控件(ImageView)的大小对Bitmap进行裁剪,减少Bitmap占用过多的内存
较好的控制图片的加载过程,例如暂停图片加载,重新开始加载图片,一般使用在ListView,GridView中,滑动过程中暂停加载图片,停止滑动的时候去加载图片
提供在较慢的网络下对图片进行加载
使用过程:
创建默认的ImageLoader,所有的操作都由ImageLoader控制。该类使用单例设计模式,所以如果要获取该类的实力,需要调用getInstance()方法。在使用ImageLoader显示图片之前,你首先要初始化它的配置,调用ImageLoaderConfiguration的init()方法,然后你就可以实现各种的显示了。
//创建默认的ImageLoader配置参数 ImageLoaderConfigurationconfiguration=ImageLoaderConfiguration .createDefault(this); //InitializeImageLoaderwithconfiguration. ImageLoader.getInstance().init(configuration);
自定义配置imageloader,就像你已经知道的,首先,你需要使用ImageLoaderConfiguration对象来初始化ImageLoader。由于ImageLoader是单例,所以在程序开始的时候只需要初始化一次就好了。建议你在Activity的onCreate()方法中初始化。如果一个ImageLoader已经初始化过,再次初始化不会有任何效果。下面我们通过ImageLoaderConfiguration.Builder创建一个设置
FilecacheDir=StorageUtils.getOwnCacheDirectory(this,"imageloader/Cache"); ImageLoaderConfigurationconfig=newImageLoaderConfiguration .Builder(this) .memoryCacheExtraOptions(480,800)//maxwidth,maxheight,即保存的每个缓存文件的最大长宽 .threadPoolSize(3)//线程池内加载的数量 .threadPriority(Thread.NORM_PRIORITY-2) .denyCacheImageMultipleSizesInMemory() .memoryCache(newUsingFreqLimitedMemoryCache(2*1024*1024))//Youcanpassyourownmemorycacheimplementation/你可以通过自己的内存缓存实现 .memoryCacheSize(2*1024*1024) .discCacheSize(50*1024*1024) .discCacheFileNameGenerator(newMd5FileNameGenerator())//将保存的时候的URI名称用MD5加密 .tasksProcessingOrder(QueueProcessingType.LIFO) .discCacheFileCount(100)//缓存的文件数量 .discCache(newUnlimitedDiscCache(cacheDir))//自定义缓存路径 .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) .imageDownloader(newBaseImageDownloader(this,5*1000,30*1000))//connectTimeout(5s),readTimeout(30s)超时时间 .writeDebugLogs()//Removeforreleaseapp .build();//开始构建 ImageLoader.getInstance().init(config);
得到imageLoader
ImageLoaderimageLoaderimageLoader=ImageLoader.getInstance();
使用过程:
(1)图像操作是否参与缓存以及图像效果的配置操作
DisplayImageOptionsoptions=newDisplayImageOptions.Builder() .showImageOnLoading(R.drawable.ic_stub)//加载图片时的图片 .showImageForEmptyUri(R.drawable.ic_empty)//没有图片资源时的默认图片 .showImageOnFail(R.drawable.ic_error)//加载失败时的图片 .cacheInMemory(true)//启用内存缓存 .cacheOnDisk(true)//启用外存缓存 .considerExifParams(true)//启用EXIF和JPEG图像格式 .displayer(newRoundedBitmapDisplayer(20))//设置显示风格这里是圆角矩形 .build();
DisplayImageOptions以下是所有默认配置参数根据需求可以自定义配置
privateintimageResOnLoading=0; privateintimageResForEmptyUri=0; privateintimageResOnFail=0; privateDrawableimageOnLoading=null; privateDrawableimageForEmptyUri=null; privateDrawableimageOnFail=null; privatebooleanresetViewBeforeLoading=false; privatebooleancacheInMemory=false; privatebooleancacheOnDisk=false; privateImageScaleTypeimageScaleType=ImageScaleType.IN_SAMPLE_POWER_OF_2; privateOptionsdecodingOptions=newOptions(); privateintdelayBeforeLoading=0; privatebooleanconsiderExifParams=false; privateObjectextraForDownloader=null; privateBitmapProcessorpreProcessor=null; privateBitmapProcessorpostProcessor=null; privateBitmapDisplayerdisplayer=DefaultConfigurationFactory.createBitmapDisplayer(); privateHandlerhandler=null; privatebooleanisSyncLoading=false;
(2)图片加载监听器在这里吧可以设置加载时的动画或者进度条之类的东西这里
ImageLoadingListeneranimateFirstListener=newAnimateFirstDisplayListener(); privatestaticclassAnimateFirstDisplayListenerextendsSimpleImageLoadingListener{ staticfinalList<String>displayedImages=Collections.synchronizedList(newLinkedList<String>()); @Override publicvoidonLoadingComplete(StringimageUri,Viewview,BitmaploadedImage){ if(loadedImage!=null){ ImageViewimageView=(ImageView)view; booleanfirstDisplay=!displayedImages.contains(imageUri); if(firstDisplay){ FadeInBitmapDisplayer.animate(imageView,500); displayedImages.add(imageUri); } } } }
(3)简单设置就可以给ImageView添加图片了
imageLoader.displayImage(imageUrl,imageview,options,animateFirstListener);
对于本地的图片,在其绝对地址前面要加入"file://"。网络图片就直接写路径了。
由于我的这个是最新的包,可能跟以前老的版本不同,看到有些网友说的是:
StringimageUri="http://site.com/image.png";//网络图片 StringimageUri="file:///mnt/sdcard/image.png";//SD卡图片 StringimageUri="content://media/external/audio/albumart/13";//媒体文件夹 StringimageUri="assets://image.png";//assets StringimageUri="drawable://"+R.drawable.image;//drawable文件
缓存的清理:
缓存的清理可以按需求来定,可以再每个Activity的生命周期函数onDestroy中清理也可以单独设置让用户自行清理。
@Override publicvoidonDestroy(){ super.onDestroy(); imageLoader.clearMemoryCache(); imageLoader.clearDiskCache(); }
GirdView,ListView加载图片:
相信大部分人都是使用GridView,ListView来显示大量的图片,而当我们快速滑动GridView,ListView,我们希望能停止图片的加载,而在GridView,ListView停止滑动的时候加载当前界面的图片,这个框架当然也提供这个功能,使用起来也很简单,它提供了PauseOnScrollListener这个类来控制ListView,GridView滑动过程中停止去加载图片,该类使用的是代理模式
listView.setOnScrollListener(newPauseOnScrollListener(imageLoader,pauseOnScroll,pauseOnFling)); gridView.setOnScrollListener(newPauseOnScrollListener(imageLoader,pauseOnScroll,pauseOnFling));
第一个参数就是我们的图片加载对象ImageLoader,第二个是控制是否在滑动过程中暂停加载图片,如果需要暂停传true就行了,第三个参数控制猛的滑动界面的时候图片是否加载
OutOfMemoryError:
虽然这个框架有很好的缓存机制,有效的避免了OOM的产生,一般的情况下产生OOM的概率比较小,但是并不能保证OutOfMemoryError永远不发生,这个框架对于OutOfMemoryError做了简单的catch,保证我们的程序遇到OOM而不被crash掉,但是如果我们使用该框架经常发生OOM,我们应该怎么去改善呢?
减少线程池中线程的个数,在ImageLoaderConfiguration中的(.threadPoolSize)中配置,推荐配置1-5
在DisplayImageOptions选项中配置bitmapConfig为Bitmap.Config.RGB_565,因为默认是ARGB_8888,使用RGB_565会比使用ARGB_8888少消耗2倍的内存
在ImageLoaderConfiguration中配置图片的内存缓存为memoryCache(newWeakMemoryCache())或者不使用内存缓存
在DisplayImageOptions选项中设置.imageScaleType(ImageScaleType.IN_SAMPLE_INT)或者imageScaleType(ImageScaleType.EXACTLY)
通过上面这些,相信大家对Universal-Image-Loader框架的使用已经非常的了解了,我们在使用该框架的时候尽量的使用displayImage()方法去加载图片,loadImage()是将图片对象回调到ImageLoadingListener接口的onLoadingComplete()方法中,需要我们手动去设置到ImageView上面,displayImage()方法中,对ImageView对象使用的是Weakreferences,方便垃圾回收器回收ImageView对象,如果我们要加载固定大小的图片的时候,使用loadImage()方法需要传递一个ImageSize对象,而displayImage()方法会根据ImageView对象的测量值,或者android:layout_widthandandroid:layout_height设定的值,或者android:maxWidthand/orandroid:maxHeight设定的值来裁剪图片