- 请求分发模块。负责封装请求,对请求进行优先级排序,并按照类型进行分发。
- 缓存模块。通常包括一个二级的缓存,内存缓存、磁盘缓存。并预置多种缓存策略。
- 下载模块。负责下载网络图片。
- 监控模块。负责监控缓存命中率、内存占用、加载图片平均耗时等。
- 图片处理模块。负责对图片进行压缩、变换等处理。
- 本地资源加载模块。负责加载本地资源,如assert、drawable、sdcard等。
- 显示模块。负责将图片输出显示。
Android平台图片加载库现状
目前社区主流的图片加载库有Universal Image Loader,Picasso,Volley,Fresco,Glide.
Picasso简介
A powerful image downloading and caching library for Android,developed by Square
Picasso的特性
- 绝对是最轻量的图片加载库,120kb.
- 自带监控功能,可以检测cache hit/内存大小等等数据
- 图片预加载
- 线程并发数依网络状态变化而变化、优先级调度
- 图片变换
- 图片压缩、自适应
- 易扩展
Picasso的使用
- 加载一张网络图片到
ImageView
上
Picasso.with(context)
.load(url)
.placeholder(R.drawable.user_placeholder)
.error(R.drawable.user_placeholder_error)
.into(imageView);//此种策略并不会压缩图片
- 预加载一张图片
Picasso.with(this).load(URL).fetch();
Picasso.with(this).load(URL).fetch(Callback);
注意哦,如果你以以下面这种方式加上图形变换preload的话:
Picasso.with(this).load(URL).rotate(20).fetch();
再下面这种方式是取不到preload的图片的,因为预缓存的是经过变换后的图片,它的cachekey会有rotation
标识
Picasso.with(this).load(URL).into(imageView);
当然我说的是preload到内存中的那份经过旋转的图片,http会缓存旋转前的图片到磁盘(支持缓存的情况下),所以最终还是可以从磁盘缓存
拿到图片的。
- 替换默认的
Picasso
Picasso p = new Picasso.Builder(this).executor().downloader(downloader).memoryCache(cache).build();
Picasso.setSingletonInstance(p);
- 同步call
new AsyncTask<Void,Void,Bitmap>(){
@Override
protected Bitmap doInBackground(Void... params) {
try {
return Picasso.with(PicassoTestActivity.this).load(URL).get();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if(bitmap != null){
imageView.setImageBitmap(bitmap);
}
}
}.execute();
注意,必须在异步线程调用,否则crash,另外,这个结果并不会缓存到内存里面,所以慎用。
- 自适应
Picasso.with(TestImageActivity.this).load(url).fit().into(imageview);
fit
方法的意思是,让图片的宽高恰好等于imageView
的宽高.前提是你的imageView控件不能设置成wrap_content
,也就是必须
有大小才行。另外,如果使用了fit
方法,那么就不能调用resize
.
- 压缩到指定尺寸
Picasso.with(TestImageActivity.this).load(url).resize(widthPixel,heightPixel).centerInside().into(imageView);
Picasso.with(TestImageActivity.this).load(URL).resizeDimen(R.dimen.width,R.dimen.height).centerCrop().into(iv);
resize
后面通常接centerInside
或者centerCrop
。注意这跟ImageView的scaleTyoe
没有关系,仅仅指的是图片的缩放方式。
比如如下代码,iv不压缩,iv_2宽高压缩到40dp并且指定为centerInside
.
<ImageView
android:id="@+id/iv"
android:background="#000"
android:layout_width="100dp"
android:layout_height="100dp"/>
<ImageView
android:layout_below="@id/iv"
android:id="@+id/iv_2"
android:background="#000"
android:layout_width="100dp"
android:layout_height="100dp"/>
Picasso.with(TestImageActivity.this).load(URL).into(iv);
Picasso.with(TestImageActivity.this).load(URL).resizeDimen(R.dimen.width/*40dp*/, R.dimen.height/*40dp*/).centerInside().into(iv_2);
最终显示结果如下:
可以很明显看到下面的图模糊许多,这是因为图片被压缩了,但是显示的时候又被ImageView拉伸了(默认scaleType是fitCenter),
要想不显示拉伸的图,可以给iv_2增加scaleType="centerInside"
,效果如下:
- 图形变换
Picasso.with(TestImageActivity.this).load(URL).rotate(20).into(iv);
//自定义变换
Picasso.with(TestImageActivity.this).load(URL).transform(new Transformation() {
@Override
public Bitmap transform(Bitmap source) {//从原图中间裁剪一个正方形
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap result = Bitmap.createBitmap(source, x, y, size, size);
if (result != source) {
source.recycle();
}
return result;
}
@Override
public String key() {
return "square()";
}
}).into(iv);