Android开源框架 universal-Image-Loader
2016-06-15 21:16
309 查看
universal-Image-Loader
在做安卓开发的时候,肯定会接触到异步夹在图片或者大量加载图片的情况。作为新手肯定会遇到很多问题,如OOM或者图片错误等问题。因此有许多图片加载的开源框架供我们使用,今天学习一下universal-Image-Loader框架。这个框架的github地址为 https://github.com/nostra13/Android-Universal-Image-Loader。在github上的介绍我们可以看到,该框架支持的URL类型很多,从web、sdcard、contentProvider、assets、drawable等都可以加载图片
"http://site.com/image.png" // from Web "file:///mnt/sdcard/image.png" // from SD card "file:///mnt/sdcard/video.mp4" // from SD card (video thumbnail) "content://media/external/images/media/13" // from content provider "content://media/external/video/media/13" // from content provider (video thumbnail) "assets://image.png" // from assets "drawable://" + R.drawable.img // from drawables (non-9patch images)
另外作者提示我们
Use drawable:// only if you really need it! Always consider the native way to load drawables - ImageView.setImageResource(…) instead of using of ImageLoader.
一般情况下加载drawable文件里面的图片时,都使用setImageResource(…),除非really need universal-Image-Loader时再使用。
universal-Image-Loader的特征
多线程下载图片,图片可以来源于网络,文件系统,项目文件夹assets中以及drawable中等支持随意的配置ImageLoader,例如线程池,图片下载器,内存缓存策略,硬盘缓存策略,图片显示选项以及其他的一些配置
支持图片的内存缓存,文件系统缓存或者SD卡缓存
支持图片下载过程的监听
根据控件(ImageView)的大小对Bitmap进行裁剪,减少Bitmap占用过多的内存
较好的控制图片的加载过程,例如暂停图片加载,重新开始加载图片,一般使用在ListView,GridView中,滑动过程中暂停加载图片,停止滑动的时候去加载图片
提供在较慢的网络下对图片进行加载
universal-Image-Loader的使用
要使用这个开源框架,eclipse上需要将这个框架的jar包导入libs文件,并且Add to build path.然后再项目属性里面Order and Export属性里面将这个框架前面的对勾打上。至于Android studio就不知道了,由于电脑较渣,运行太卡。新建一个MyApplication类,在这里面进行universal-Image-Loader的配置
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); ImageLoaderConfiguration config=ImageLoaderConfiguration.createDefault(this); ImageLoader.getInstance().init(config); } }
ImageLoaderConfiguration是ImageLoader的配置参数,在这里直接使用了createDefault()创建了一个默认的,一般默认的就可以了,当然也可以自定义参数,可设置的参数如下
File cacheDir = StorageUtils.getCacheDirectory(context); ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context) .memoryCacheExtraOptions(480, 800) // default = device screen dimensions .diskCacheExtraOptions(480, 800, CompressFormat.JPEG, 75, null) .taskExecutor(...) .taskExecutorForCachedImages(...) .threadPoolSize(3) // default .threadPriority(Thread.NORM_PRIORITY - 1) // default .tasksProcessingOrder(QueueProcessingType.FIFO) // default .denyCacheImageMultipleSizesInMemory() .memoryCache(new LruMemoryCache(2 * 1024 * 1024)) .memoryCacheSize(2 * 1024 * 1024) .memoryCacheSizePercentage(13) // default .diskCache(new UnlimitedDiscCache(cacheDir)) // default .diskCacheSize(50 * 1024 * 1024) .diskCacheFileCount(100) .diskCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default .imageDownloader(new BaseImageDownloader(context)) // default .imageDecoder(new BaseImageDecoder()) // default .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default .writeDebugLogs() .build();
然后调用ImageLoader的init方法将配置的参数传递进去,getInstance方法表明ImageLoader是单例模式。
然后注意配置AndroidManifest.xml文件,将MyApplication配置上,并且加上网络访问和读取外部存储的权限。
开始使用
布局文件,一个ImageView
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage}.${activityClass}" > <ImageView android:id="@+id/third_show_ImageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" ></ImageView> </RelativeLayout>
ImageLoader主要有以下下载图片的方法
其中loadImageSync方法是同步的。
首先使用loadImage方法
mShowImageView=(ImageView) findViewById(R.id.third_show_ImageView); String imageUrl="http://d.hiphotos.baidu.com/baike/w%3D268%3Bg%3D0/sign=abab84ca2af5e0feee188e07645b5395/a8014c086e061d9551cfbceb7cf40ad163d9ca5c.jpg"; ImageLoader.getInstance().loadImage(imageUrl, new ImageLoadingListener() { @Override public void onLoadingCancelled(String arg0, View arg1) { } @Override public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) { Log.i(TAG, Thread.currentThread().getName()+"--------------"); mShowImageView.setImageBitmap(arg2); } @Override public void onLoadingFailed(String arg0, View arg1, FailReason arg2) { } @Override public void onLoadingStarted(String arg0, View arg1) { } });
可以看到,只需要将需要下载的图片的url地址传进去,并且监听图片下载,还可以重写四个方法,对下载开始,下载取消,下载完成,下载失败,分别进行处理。下载完成的三个参数分别为
String imageUri; View view Bitmap loadedImage;
如果想简单一点,只对下载完成进行处理
ImageLoader.getInstance().loadImage(imageUrl, new SimpleImageLoadingListener(){ @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { super.onLoadingComplete(imageUri, view, loadedImage); mShowImageView.setImageBitmap(loadedImage); } });
只需要监听SimpleImageLoadingListener接口就可以了,只需要实现下载完成的方法。
如果需要指定图片的大小,初始化一个ImageSize,设置宽和高,然后调用ImageLoader的另一个重载的方法将size传递进去。
ImageSize size=new ImageSize(200, 200); ImageLoader.getInstance().loadImage(imageUrl, size,new SimpleImageLoadingListener(){ @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { super.onLoadingComplete(imageUri, view, loadedImage); mShowImageView.setImageBitmap(loadedImage); } });
以上只是简单使用,如果需要配置信息
可以配置的信息有
DisplayImageOptions options = new DisplayImageOptions.Builder() .showImageOnLoading(R.drawable.ic_stub) // resource or drawable .showImageForEmptyUri(R.drawable.ic_empty) // resource or drawable .showImageOnFail(R.drawable.ic_error) // resource or drawable .resetViewBeforeLoading(false) // default .delayBeforeLoading(1000) .cacheInMemory(false) // default .cacheOnDisk(false) // default .preProcessor(...) .postProcessor(...) .extraForDownloader(...) .considerExifParams(false) // default .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default .bitmapConfig(Bitmap.Config.ARGB_8888) // default .decodingOptions(...) .displayer(new SimpleBitmapDisplayer()) // default .handler(new Handler()) // default .build();
将上面的代码修改一下
ImageSize size=new ImageSize(200, 200); //显示图片的配置 DisplayImageOptions options=new DisplayImageOptions.Builder() //使用内存缓存 .cacheInMemory(true) //使用文件缓存 .cacheOnDisc(true) .bitmapConfig(Bitmap.Config.RGB_565) .build(); ImageLoader.getInstance().loadImage(imageUrl, size, options,new SimpleImageLoadingListener(){ @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { super.onLoadingComplete(imageUri, view, loadedImage); mShowImageView.setImageBitmap(loadedImage); } });
这里配置将图片加载到缓存中,就不需要每次从网络上下载了,但是DisplayImageOptions的一些配置对loadImage是无效的,比如设置下载失败的图片和正在下载的图片等
使用displayImage()方法
修改代码DisplayImageOptions options2=new DisplayImageOptions.Builder() .cacheInMemory(true) .cacheOnDisc(true) .bitmapConfig(Bitmap.Config.RGB_565) .showImageOnLoading(R.drawable.loading_default_small) .showImageOnFail(R.drawable.icon_fail) .build(); ImageLoader.getInstance().displayImage(imageUrl, mShowImageView, options2,new SimpleImageLoadingListener(), new ImageLoadingProgressListener() { @Override public void onProgressUpdate(String imageUrl, View view, int current, int total) { } });
可以看到使用非常简单,并且它会根据控件的大小和ImageScaleTyle的类型来裁剪图片,而且不需要手动设置bitmap对象,只需要将控件作为参数传递进去就可以了。在我们加载图片的时候,经常需要显示进度,displayImage方法也提供了这样的接口,使用方法上面的代码已经实现了。
加载其他来源的图片
加载文件系统String imagePath = "/mnt/sdcard/image.png"; String imageUrl = Scheme.FILE.wrap(imagePath);
加载contentProvider
String contentprividerUrl = "content://media/external/audio/albumart/13";
加载assets
String assetsUrl = Scheme.ASSETS.wrap("image.png");
加载drawable
String drawableUrl = Scheme.DRAWABLE.wrap("R.drawable.image");
可以看到,除了contentProvider外,其他的都是在原地址上使用Scheme进行wrap一下生成新的Url即可。
GirdView,ListView加载图片
而当我们快速滑动GridView,ListView,我们希望能停止图片的加载,而在GridView,ListView停止滑动的时候加载当前界面的图片,这个框架当然也提供这个功能,使用起来也很简单,它提供了PauseOnScrollListener这个类来控制ListView,GridView滑动过程中停止去加载图片,该类使用的是代理模式listView.setOnScrollListener(new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling)); gridView.setOnScrollListener(new PauseOnScrollListener(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(new WeakMemoryCache()) 或者不使用内存缓存
在DisplayImageOptions选项中设置.imageScaleType
(ImageScaleType.IN_SAMPLE_INT)
或者imageScaleType(ImageScaleType.EXACTLY)
推荐使用displayImage()
displayImage()方法中,对ImageView对象使用的是Weak references,方便垃圾回收器回收ImageView对象,如果我们要加载固定大小的图片的时候,使用loadImage()方法需要传递一个ImageSize对象,而displayImage()方法会根据ImageView对象的测量值,或者android:layout_width and android:layout_height设定的值,或者android:maxWidth and/or android:maxHeight设定的值来裁剪图片
本文大量参考了xiaanming的博客,博客地址
http://blog.csdn.net/xiaanming/article/details/26810303相关文章推荐
- com.android.dex.DexException: Multiple dex files define(重复引用包)
- 安卓自带下拉刷新SwipeRefreshLayout添加上拉刷新功能
- Android源码浅析(三)——Android AOSP 5.1.1源码的同步sync和编译make,搭建Samba服务器进行更便捷的烧录刷机
- Android源码浅析(三)——Android AOSP 5.1.1源码的同步sync和编译make,搭建Samba服务器进行更便捷的烧录刷机
- 调整Android手机的默认亮度
- Android显示系统_由浅入深_02_动画与其他常用类
- Android Studio 问题汇总目录
- Android中Intent介绍
- android进程重启及activity恢复
- Android之BroadcastReceiver(二):接收系统广播
- Android JAVA中去掉字符串空格的方法
- Android天气预报开发
- Android Studio使用gradle-retrolambda支持Java8 新特性 Lambde表达式
- Android拨打电话
- Android开发学习笔记之通过API接口将LaTex数学函数表达式转化为图片形式
- android Fragment 源码分析
- 深入理解Android的startservice和bindservice
- 我的第一个Android程序--HelloWorld
- Android中的dex分包
- Android Studio提示忽略大小写