大家在做Android开发时,经常需要用到异步加载图片,在这里主要介绍最常用的一个工具
Universal-Image-Loader,相信很多朋友都听过或者使用过这个强大的图片加载框架。有关Universal-Image-Loader的使用可以参考 https://github.com/nostra13/Android-Universal-Image-Loader,看一看到主要有以下特征:
Features
- Multithread image loading (async or sync)
- Wide customization of ImageLoader's configuration (thread executors, downloader, decoder, memory and disk cache, display image options, etc.)
- Many customization options for every display image call (stub images, caching switch, decoding options, Bitmap processing and displaying, etc.)
- Image caching in memory and/or on disk (device's file system or SD card)
- Listening loading process (including downloading progress)
Android 2.0+ support
接下来看一下Universal-Image-Loader开源库的使用。在这里要说明一下我用到的开发工具是Android Studio。
1.创建一个Android工程目录,并把Universal-Image-Loader放在libs文件夹下。
2.配置ImageLoaderConfiguration,这个是图片加载器ImageLoader的配置参数。可以选择在Application中配置,目的的每次用到的时候不用重复写代码。
Application和Activity,Service一样是Android框架的一个系统组件,当Android程序启动时系统会创建一个Application对象,用来存储系统的一些信息。
Android系统自动会为每个程序运行时创建一个Application类的对象且只创建一个,所以Application可以说是单例(singleton)模式的一个类。
通常我们是不需要指定一个Application的,系统会自动帮我们创建,如果需要创建自己的Application,那也很简单!创建一个类继承Application并在AndroidManifest.xml文件中的application标签中进行注册(只需要给application标签增加name属性,并添加自己的 Application的名字即可)。
启动Application时,系统会创建一个PID,即进程ID,所有的Activity都会在此进程上运行。那么我们在Application创建的时候初始化全局变量,同一个应用的所有Activity都可以取到这些全局变量的值,换句话说,我们在某一个Activity中改变了这些全局变量的值,那么在同一个应用的其他Activity中值就会改变。
Application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。所以可以通过Application来进行一些,如:数据传递、数据共享和数据缓存等操作。
注:继承Application类,主要重写里面的onCreate()方法(android.app.Application包的onCreate()才是真正的Android程序的入口点),就是创建的时候,初始化变量的值。然后在整个应用中的各个文件中就可以对该变量进行操作了。
新建一个MyApplication继承Application,并在onCreate()中创建ImageLoader的配置参数
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
initImageLoader(getApplicationContext());
}
private void initImageLoader(Context context){
/**定义缓存文件的目录**/
File cacheDir= StorageUtils.getOwnCacheDirectory(getApplicationContext(),"Cache/");
/**ImageLoader的配置**/
ImageLoaderConfiguration config=new ImageLoaderConfiguration.Builder(context)
.threadPriority(Thread.NORM_PRIORITY-2) //设置同时运行的线程
.denyCacheImageMultipleSizesInMemory() //缓存显示不同大小的同一张图片
.diskCacheSize(50*1024*1024) //50MB SD卡本地缓存的最大值
.diskCache(new UnlimitedDiscCache(cacheDir)) //SD卡缓存
.memoryCache(new WeakMemoryCache()) //内存缓存
.tasksProcessingOrder(QueueProcessingType.LIFO).build();
//全局初始化配置
ImageLoader.getInstance().init(config);
}
}
<span style="color:#3333ff;">后面附上网上比较全的配置信息,实际上不用每一个都用到。</span>
<pre name="code" class="java">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();
不要忘了在AndroidManifest中注册MyApplication,加入权限。
3 ImageLoader加载图片
使用ImageLoader加载图片时,首先要实例化ImageLoader。ImageLoader的实例化采用的是单例模式。
ImageLoader loader=ImageLoader.getInstance();
ImageLoader加载图片分为两种情况,一种是默认的加载。
loader.displayImage(imgUrl,img);//参数1--要加载图片的url地址,参数2--要显示图片的控件,可以为ImageView<span style="font-family: Arial;"> </span>
另一种是通过DisplayImageOptions 自定义要显示的图片。
加载图片的方法是:
loader.displayImage(imgUrl,img,options);
options在下面定义
DisplayImageOptions options=new DisplayImageOptions.Builder()
.showImageOnLoading(drawableID) //设置正在下载时显示的图片
.showImageForEmptyUri(drawableID) //设置Url为空时显示的图片
.showImageOnFail(drawableID) //设置图片下载失败时显示的图片
.cacheInMemory(true) //允许图片保存到手机内存
.cacheOnDisk(true) //允许图片保存到SD卡中
.considerExifParams(true) //是否考虑JPEG图像EXIF参数(旋转,翻转)
.bitmapConfig(Bitmap.Config.RGB_565)
.build(); //构建完成
附上网上比较全的配置信息
<pre name="code" class="java">DisplayImageOptions options;
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_launcher) //设置图片在下载期间显示的图片
.showImageForEmptyUri(R.drawable.ic_launcher)//设置图片Uri为空或是错误的时候显示的图片
.showImageOnFail(R.drawable.ic_launcher) //设置图片加载/解码过程中错误时候显示的图片
.cacheInMemory(true)//设置下载的图片是否缓存在内存中
.cacheOnDisc(true)//设置下载的图片是否缓存在SD卡中
.considerExifParams(true) //是否考虑JPEG图像EXIF参数(旋转,翻转)
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED)//设置图片以如何的编码方式显示
.bitmapConfig(Bitmap.Config.RGB_565)//设置图片的解码类型//
.decodingOptions(android.graphics.BitmapFactory.Options decodingOptions)//设置图片的解码配置
//.delayBeforeLoading(int delayInMillis)//int delayInMillis为你设置的下载前的延迟时间
//设置图片加入缓存前,对bitmap进行设置
//.preProcessor(BitmapProcessor preProcessor)
.resetViewBeforeLoading(true)//设置图片在下载前是否重置,复位
.displayer(new RoundedBitmapDisplayer(20))//是否设置为圆角,弧度为多少
.displayer(new FadeInBitmapDisplayer(100))//是否图片加载好后渐入的动画时间
.build();//构建完成
4.注意事项
1.上述提到的2个权限必须加入,否则会出错
2.ImageLoaderConfiguration必须配置并且全局化的初始化这个配置ImageLoader.getInstance().init(config); 否则也会出现错误提示
3.ImageLoader是根据ImageView的height,width确定图片的宽高。
4.如果经常出现OOM(别人那边看到的,觉得很有提的必要)
①减少配置之中线程池的大小,(.threadPoolSize).推荐1-5;
②使用.bitmapConfig(Bitmap.config.RGB_565)代替ARGB_8888;
③使用.imageScaleType(ImageScaleType.IN_SAMPLE_INT)或者 try.imageScaleType(ImageScaleType.EXACTLY);
④避免使用RoundedBitmapDisplayer.他会创建新的ARGB_8888格式的Bitmap对象;
⑤使用.memoryCache(new WeakMemoryCache()),不要使用.cacheInMemory();
5.从其他路径加载图片的url
多线程异步加载和显示图片(图片来源于网络、sd卡、assets文件夹,drawable文件夹(不能加载9patch),新增加载视频缩略图)
"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)