以前都是使用xUtils,觉得xUtils集成的Db、View、Http、Bitmap这四个模块的功能已经非常全,没必要再引入新的开源模块增加维护的难度以及不可控bug的可能性。
那么先看看bitmapUtils是怎么说的。
- BitmapUtils模块:
- 加载bitmap的时候无需考虑bitmap加载过程中出现的oom和android容器快速滑动时候出现的图片错位等现象;
- 支持加载网络图片和本地图片;
- 内存管理使用lru算法,更好的管理bitmap内存;
- 可配置线程加载线程数量,缓存大小,缓存路径,加载显示动画等…
BitmapUtils bitmapUtils = new BitmapUtils(this);
// 加载网络图片
bitmapUtils.display(testImageView, "http://bbs.lidroid.com/static/image/common/logo.png");
// 加载本地图片(路径以/开头, 绝对路径)
bitmapUtils.display(testImageView, "/sdcard/test.jpg");
// 加载assets中的图片(路径以assets开头)
bitmapUtils.display(testImageView, "assets/img/wallpaper.jpg");
// 使用ListView等容器展示图片时可通过PauseOnScrollListener控制滑动和快速滑动过程中时候暂停加载图片
listView.setOnScrollListener(new PauseOnScrollListener(bitmapUtils, false, true));
listView.setOnScrollListener(new PauseOnScrollListener(bitmapUtils, false, true, customListener));
其实到这里,需要补充说明一下图片的三级缓存,按照读取速度来分, MemoryCache DiskCache NEtRecs,自然读取内存的速度是最快的,储存卡文件次之,网络资源最慢。
三级缓存的存在一来解决频繁的网络请求,减轻服务器压力,二来实现更好的用户体验,节省用户宝贵的30M流量。那么这个逻辑顺序是,当内存中有缓存,则优先读取内存,否则读取储存卡资源,并将其加载到缓存,如果一上两者都不存在,则直接请求网络资源,加载进内存缓存,并且数据保存到储存卡本地,以供后用。这里说明一下,不是说有的内容都加载到内存中缓存的,大家都知道图片资源比较耗空间,而安卓的中端机型本来内存就捉襟见肘,所以建议以Lru实现的缓存 不要超过1/8 或者1/6,毕竟不是只运行咱这一个app。
上面说了那么多废话,开始说下uniersal_imageloader。之前看别人的博客,说京东淘宝的大神们也在用,用了都说好… … 心里还是痒痒了,于是就出来这篇,这句还是废话。
看下它的运行机制,其实还是三级缓存的那些东东… …
不过需要强调的是,它的每一个图片的加载和显示都在独立的线程,不管是读取本地还是请求网络。其实xUtils也是这么做的,但是通过异步的方法。
说下imageloader的使用吧
使用步骤:
1、欲善其事,必利其器。加载图片之前,先要做初始化配置,其实就是实例化一个全局的ImageLoader对象,同时传入图片加载缓存的配置,ImageLoaderConfiguration封装了基本的配置信息,比如加载图片事用的线程池大小,线程的优先级,内存缓存大小,是否支持同一图片的多尺寸缓存(默认是支持的,可以手动关闭),还有缓存的命名规则等等。
2、走马上任。配置完后,通过
ImageLoader.displayImage(String uri, ImageView imageView, DisplayImageOptions options)
DisplayImageOptions用于指导每一个Imageloader根据网络图片的状态(空白、下载错误、正在下载)显示对应的图片,是否将缓存加载到磁盘上,下载完后对图片进行怎么样的处理。
话不多说,上实战!
继承Application,完成ImageLoaderConfiguration。为啥?Application为应用的整体提供基础环境。
public class BaseApplication extends Application { @Override public void onCreate() { super.onCreate(); initImageLoader( getApplicationContext()); } public void initImageLoader(Context context) { //自定义缓存文件目录 File cacheDirectory = StorageUtils.getOwnCacheDirectory(context, "ImageLoader/cache"); ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context) .memoryCacheExtraOptions(480, 800) //设置内存缓存的最大宽和高 .threadPoolSize(5)//线程池的大小,以目前手机配置来说,一般3-5比较合适吧 .threadPriority(Thread.NORM_PRIORITY - 2) //线程的优先级 .denyCacheImageMultipleSizesInMemory() //关闭多规格缓存图片,为啥?浪费空间 .diskCacheFileNameGenerator( new Md5FileNameGenerator()) //图片名称采用md5加密,为啥?保护隐湿 .memoryCacheSize(1024 * 1024 * 5) //内存最大缓存值 5M .diskCacheSize(1024 * 1024 * 50) //储存卡最大缓存值 50M .tasksProcessingOrder(QueueProcessingType.LIFO) //设置任务的处理顺序 .discCache( new UnlimitedDiscCache(cacheDirectory))//使用cacheDirectory自定义存储卡缓存 .imageDownloader( new BaseImageDownloader(context, 1000 * 3, 1000 * 15)) //连接超时时间,读取小时时间 .writeDebugLogs() //写调试信息 .build(); //配置完毕 ImageLoader.getInstance().init(config);//全局初始化完毕。 }
}
配置一般的listview 应用环境 ,关键在于 Adapter的处理。
private class MyBaseAdapter extends BaseAdapter{ @Override public int getCount() { return imageUrls.length; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view; ViewHolder mHolder; if (convertView != null) { view = convertView; mHolder = (ViewHolder) view.getTag(); } else { view = View.inflate(MainActivity.this, R.layout.item_listview, null); mHolder = new ViewHolder(); mHolder.image = (ImageView) view.findViewById(R.id.iv_items_image); mHolder.text = (TextView) view.findViewById(R.id.tv_items_text); view.setTag(mHolder); } imageLoader.displayImage(imageUrls[position], mHolder.image, options); mHolder.text.setText("我是你的小苹果"); return view; } }
imageLoader.displayImage(imageUrls[position], mHolder.image, options);//设置imageview的图像资源, 关键是后边的option,它决定了对图像的处理过程。
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_stub)//加载时显示的图片
.showImageForEmptyUri(R.drawable.ic_empty) //无效链接时显示的图片
.showImageOnFail(R.drawable.ic_error) //加载失败时的图片
.cacheInMemory(true) //加载进缓存
.cacheOnDisk(true) //保存到本地
.displayer( new RoundedBitmapDisplayer(20) ) //圆角展示,倒角半径
.build();
3.权限处理 WRITE_EXTERNAL_SDCARD + INTERNET
4.application节点配置
最后老套路,直接上代码。