框架学习四-2:处理OOM之Universal-Image-Loader

转自:http://blog.csdn.net/xiaanming/article/details/26810303

一、简介

相比上一篇来说,这个Universal-Image-Loader太大了。它功能强大,可扩展性好,高度可定制。

特征:

1)多线程下载图片,图片可来源于网络,文件系统,项目文件夹assets及drawable中等。

2)支持随意的配置ImageLoader,例如线程池,图片下载器,内存缓存策略,图片显示选项及其他一些配置。

3)支持图片的内存缓存,文件系统缓存或SD卡缓存。

4)支持图片下载过程的监听。

5)根据ImageView控件大小对Bitmap进行裁剪,减少Bitmap占用过多的内存。

6)较好的控制图片的加载过程,例如暂停图片加载,重新开始加载图片,一般使用ListView,GridView中,滑动过程中暂停加载图片,停止滑动的时候去加载图片。

7)提供在较慢的网络下对图片进行加载。

二、下载地址和支持版本

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

支持版本:2.0+

三、加载网络图片用法

1、下载JAR并导入到libs。

2、声明网络权限和访问SD卡权限。

3、新建一个MyApplication继承Application或新建一个Activity继承Activity,在onCreate()中配置ImageLoader的参数,并初始化到代码中。

public class MyApplication extends Application {  
  
    @Override  
    public void onCreate() {  
        super.onCreate();  
  
        //创建默认的ImageLoader配置参数  
        ImageLoaderConfiguration configuration = ImageLoaderConfiguration  
                .createDefault(this);  
          
        //Initialize ImageLoader with configuration.  
        ImageLoader.getInstance().init(configuration);  
    }  
}  

DisplayImageOptions对每个显示任务来说是局部的。通过ImageLoader.displayImage()调用。

ImageLoaderConfiguration是图片加载器ImageLoader的配置参数,每个应用设置一个全局的实例即可。上面是创建了一个默认的ImageLoaderConfigurations,当然也可以自己设置ImageLoaderConfigurations。

// DON'T COPY THIS CODE TO YOUR PROJECT! This is just example of ALL options using.
// See the sample project how to use ImageLoader correctly.
File cacheDir = StorageUtils.getCacheDirectory(context);
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
        .memoryCacheExtraOptions(480, 800) // default = device screen dimensions
        .diskCacheExtraOptions(480, 800, null)
        .taskExecutor(...)
        .taskExecutorForCachedImages(...)
        .threadPoolSize(3) // default
        .threadPriority(Thread.NORM_PRIORITY - 2) // 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();
4、加载图片

注意:显示图片时最好不要用ImageLoader,而是使用ImageView.setImageResource()

final ImageView mImageView = (ImageView) findViewById(R.id.image);  
String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg";  
          
//显示图片的配置  
DisplayImageOptions options = new DisplayImageOptions.Builder()  
      .showImageOnLoading(R.drawable.ic_stub)  
      .showImageOnFail(R.drawable.ic_error)  
      .cacheInMemory(true)  
      .cacheOnDisk(true)  
      .bitmapConfig(Bitmap.Config.RGB_565)  
      .build();  
          
ImageLoader.getInstance().displayImage(imageUrl, mImageView, options);  
图片显示的配置选项中,添加了一个图片加载中ImageView显示的图片,及图片加载出现错误时显示的图片。而且displayImage()会自动根据控件大小和imageScaleType来裁剪图片。修改下MyApplication,开启log打印:

public class MyApplication extends Application {  
  
    @Override  
    public void onCreate() {  
        super.onCreate();  
  
        //创建默认的ImageLoader配置参数  
        ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(this)  
        .writeDebugLogs() //打印log信息  
        .build();  
          
          
        //Initialize ImageLoader with configuration.  
        ImageLoader.getInstance().init(configuration);  
    }  
} 

5、打印log(可有可无)

public class MyApplication extends Application {  
  
    @Override  
    public void onCreate() {  
        super.onCreate();  
  
        //创建默认的ImageLoader配置参数  
        ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(this)  
        .writeDebugLogs() //打印log信息  
        .build();  
           
        //Initialize ImageLoader with configuration.  
        ImageLoader.getInstance().init(configuration);  
    }  
} 
6、加载图片时,显示图片下载进度。

只需在displayImage()中传入ImageLoadingProgressListener接口就行了。

imageLoader.displayImage(imageUrl, mImageView, options, new SimpleImageLoadingListener(), new ImageLoadingProgressListener() {  
              
    @Override  
    public void onProgressUpdate(String imageUri, View view, int current,  
     <span style="white-space:pre">	</span>int total) {  
          
    }  
}); 
由于displayImage()中带ImageLoadingProgressListener参数的方法都有带ImageLoadingListener参数,所以这里new一个SimpleImageLoadingListener,然后就可在回调方法onProgressUpdate()得到图片的加载进度。

四、加载其他来源图片

只需将url稍加改动即可,下面是加载文件系统的图片

//显示图片的配置  
DisplayImageOptions options = new DisplayImageOptions.Builder()  
     .showImageOnLoading(R.drawable.ic_stub)  
     .showImageOnFail(R.drawable.ic_error)  
     .cacheInMemory(true)  
     .cacheOnDisk(true)  
     .bitmapConfig(Bitmap.Config.RGB_565)  
     .build();  
          
     final ImageView mImageView = (ImageView) findViewById(R.id.image);  
     String imagePath = "/mnt/sdcard/image.png";  
     String imageUrl = Scheme.FILE.wrap(imagePath);  
          
//   String imageUrl = "http://img.my.csdn.net/uploads/201309/01/1378037235_7476.jpg";  
          
     imageLoader.displayImage(imageUrl, mImageView, options);  
当图片来源于Content Provider,drawable,assets中,使用也非常简单,只需给每个图片源加上Schema包裹起来(Content Provider除外),然后当做图片的url传递到imageLoader中:

//图片来源于Content provider  
String contentprividerUrl = "content://media/external/audio/albumart/13";  
          
//图片来源于assets  
String assetsUrl = Scheme.ASSETS.wrap("image.png");  
          
//图片来源于  
String drawableUrl = Scheme.DRAWABLE.wrap("R.drawable.image");

五、GridView、ListView加载图片

当快速滚动时,希望停止加载图片,而在GridView、ListView停止滑动时加载当前界面的图片。这个框架也提供了这个功能,使用起来也简单,它提供了PauseOnScrollListener这个类来控制ListView、GridView滑动过程中停止加载图片:

listView.setOnScrollListener(new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling));  
gridView.setOnScrollListener(new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling)); 
第一个参数是图片加载对象;第二个是控制是否在滑动过程中加载图片,如果需要暂停传true即可;第三个参数控制猛的滑动界面时图片是否加载。

六、OOM问题

这个框架产生OOM的概率比较小,并不保证OOM问题永不发生。这个框架对OOM做了简单的crash,保证我们的程序遇到OOM而不被crash掉,但如果我们使用该框架经常发生OOM,该怎么去改善呢?

1、减少线程池中线程的个数。在ImageLoaderConfiguration中的(.threadPoolSize)中配置,推荐1-5。
2、在DisplayImageOptions选项中配置bitmapConfig为Bitmap.Config.RGB_565 ,因为默认是ARGB_8888,使用RGB_565会比ARGB_8888少消耗2倍内存。

3、在ImageLoaderConfiguration中配置图片的内存缓存为memoryCache(new WeakMemoryCache())或者不使用内存缓存。

4、在DisplayImageOptions选项中设置.imageScaleType(ImageScaleType.IN_SAMPLE_INT)或者imageScaleType(ImageScale.EXACTY)

七、题外话

使用这个框架时尽量使用displayImage()去加载图片,loadImage()是将图片对象回调到ImageLoadingListener接口的onLoadingComplete()中,需要手动设置到ImageView上。displayImage()中,对ImageView对象使用的是弱引用,方便垃圾回收器回收ImageView对象,如果我们加载固定大小的图片时,使用loadImage()需要传递一个ImageSize对象,而displayImage()会根据ImageView对象的测量值,或者android:layout_width和android:layout_height设定的值,或者android:maxWidth或android:maxHeight设定的值来裁剪图片。




你可能感兴趣的:(框架学习四-2:处理OOM之Universal-Image-Loader)