Picasso
Picasso是一个加载图片的库。
dependencies {
implementation 'com.squareup.picasso:picasso:2.71828'
}
基本用法
使用的是最新的Picasso版本,api用法和先前的一些版本不太一致。
Picasso加载图片的方式很简单,代码如下:
Picasso.get()
.load(R.mipmap.avatar)
.into(mImageView1);
加载的图片来源:
Picasso加载图片资源的来源如下四种:
1 . 从assets中加载:
Picasso.get()
.load("file:///android_asset/header.jpeg")
.into(mImageView2);
2 . 从res资源id中加载
Picasso.get()
.load(R.mipmap.avatar)
.into(mImageView1);
//也可以用下面的方式来加载res文件夹中的图片资源;
Picasso.get()
.load("android.resource://com.example.kang/mipmap/avatar")
.into(mImageView1);
3 . 从本地存储中加载
String path = "file://" + Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/image.jpg";
Picasso.get()
.load(path)
.into(mImageView3);
4 . 从网络资源中加载
Picasso.get()
.load("http://dmimg.5054399.com/allimg/pkm/pk/13.jpg")
.into(mImageView4);
从上面简单的代码中,其实Picasso调用api是有一定的顺序的,比如需要是Picasso.get().load()这样的开头,以into()方法结尾。在load()和into()方法之间可以添加一些api方法对图片进行一定的处理。其实这里面涉及到Picasso源码中的两个类:Picasso和RequestCreator。
在Picasso这个类中,我们常用的方法有:
方法名 | 解释 |
---|---|
get() | 构造Picasso对象 |
load() | 加载图片资源 |
在RequestCreator类中,常用的方法有:
方法名 | 解释 |
---|---|
placeholder() | 设置加载中显示的占位图; |
error() | 设置加载错误时显示的图片(如果加载发生错误会重复三次请求,三次都失败才会显示预设的错误图片); |
resize() | 设置指定大小的图片(指的是图片宽高的像素点的值,而不是图片的宽高); |
resizeDimen() | 设置指定大小的图片,指的是图片宽高占用的 |
centerCrop() | 按比例裁减图片,使其居中显示,充满View,会造成图片显示不全,必须与resize()方法同时使用; |
centerInside() | 按比例裁减图片,图片可以完全显示,但如果图片比View小,则无法充满整个View,必须与resize()方法同时使用; |
fit() | 设置图片的宽高等于控件的宽高,属于非等比拉伸填满控件,不能和resize()方法一起使用; |
rotate() | 旋转,比如设置rotate(90),就是顺时针旋转90度; |
noFade() | 取消图片的过渡显示效果; |
config() | 设置图片质量,默认使用ARGB_8888,参数有ALPHA_8(每个像素占用1byte内存)、RGB_565(每个像素占用2byte内存)、ARGB_4444(每个像素占用2byte内存,已经被弃用)、ARGB_8888(每个像素占用4byte内存); |
priority() | |
into() | 设置填充的View的对象; |
resize()方法的注意事项:
例如一张图片分辨率为400 * 486,Bitmap.config为ARGB_8888,即每个像素占4个字节。如果不使用resize()方法,图片所占内存大小为400 * 486 * 4个字节。如果使用resize(200,200)以后,图片所占内存大小就变为了200 * 200 * 4个字节。
但是也需要注意,resize()不仅可以缩小,同时也会放大图片。如果使用resize(3500,3500)方法加载了3500 * 3500分辨率的图片到内存中,那么所占用内存为3500 * 3500 * 4 /(1024 * 1024) = 46.7M。因此,使用resize()方法的时候,最好加上onlyScaleDown()方法,这个方法设置只缩小不放大。当resize尺寸大于Bitmap尺寸的时候,不放大图片;当resize尺寸小于Bitmap尺寸的时候,缩小照片。
当resize()的两个参数中有一个为0时,表示按照另一个非0的参数来保持宽高比。比如resize(300,0),就是图片宽度为300个像素,高度等比例拉伸。两个参数不可以同时为0,否则会报"At least one dimension has to be positive number."的错误。
fit()方法不能和resize()一起使用。centerCrop()和centerInside():
centerCrop()和centerInside()单独使用的时候,必须和resize()方法一起使用,而且centerCrop()和centerInside()这两个方法不可以同时使用。
使用Picasso设置图片的ScaleType,只有centerCrop()和centerInside()这两种类型。取消加载图片
当我们退出页面Activity/Fragment的时候,不想再加载图片,我们就需要取消请求。可以使用cancelRequest(mImageView)或Picasso.get().cancelTag(tag);
需要注意的是:如果正在下载一张图片,那么及时取消了加载图片,网络请求不会中断,仍会占用网络继续下载,但是ImageView不会收到回调。这里正在下载的意思是线程正在执行Runnable方法。如果请求在线程池的等待队列中,那么不会下载。如果是正在执行,则不会中断。暂停加载图片
Picasso的暂停加载图片,实际上是取消下载图片,并把当前请求添加到暂停列表中。使用Picasso.get().pauseTag(tag);继续加载图片
Picasso的继续加载图片,是重新把请求交给Picasso来下载,并不是断点下载。使用Picasso.get().resumeTag(tag);
暂停和继续加载图片,一般是在ListView和RecyclerView中使用的,当快速滑动的时候暂停下载图片,当滑动停止的时候继续加载图片。跳过内存缓存加载图片
有时候,我们的业务需求不需要从内存缓存中加载图片,而是想直接从磁盘或网络中加载图片,就可以设置内存策略为MemoryPolicy.NO_CACHE。使用Picasso.get().load("xxx").memoryPolicy(MemoryPolicy.NO_CACHE).into(mImageView);
如果不想把加载的图片放在内存缓存中,就使用内存策略MemoryPolicy.NO_STORE。使用Picasso.get().load("xxx").memoryPolicy(MemoryPolicy.NO_STORE).into(mImageView);
Picasso默认会使用设备的15%的内存作为内存图片缓存,且没有api可以清空内存缓存。我们一般在查看大图时放弃使用内存缓存,图片从网络下载完成后会缓存到磁盘中,加载会从磁盘中加载,这样可以加速内存的回收。
Picasso.get().load("xxx").memoryPolicy(MemoryPolicy.NO_CACHE,MemoryPolicy.NO_STORE).into(mImageView);NO_CACHE指图片加载时放弃在内存缓存中查找,NO_STORE指图片加载不缓存在内存中。
优化的地方
- 重写ImageView:
重写ImageView的onDetachedFromWindow方法,在ImageView从屏幕中消失的时候回调,去掉drawable引用,能加快内存的回收。
public class RecyclerImageView extends ImageView{
@Override
protected void onDetachedFromWindow(){
super.onDetachedFromWindow();
setImageDrawable(null);
}
}
在新进程中查看大图:
如果要查看的大图占用内存达到了几十M,再加上现有进程中的内存,就容易产生OOM。在展示图片的Activity,我们可以在Androidmanifest.xml文件中把那个展示图片的Activity设置属性android:process=":xxx",就相当于在新进程中打开这个Activity。在ListView或者RecyclerView中滑动优化:
Picasso可以对多个加载请求设置相同的tag,如下:
Object tag = new Object()
Picasso.get()
.load("xxx")
.tag(tag)
.into(mImageView);
//在RecyclerView滑动时监听,处理不同的表现;
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener(){
@Override
public void onScrollStateChanged(RecyclerView recyclerView,int newState){
if(newState == RecyclerView.SCROLL_STATE_IDLE){
Picasso.get().resumeTag(tag);
}else{
Picasso.get().pauseTag(tag);
}
}
});
- 对于不透明的图片使用RGB_565来优化内存:
java Picasso.get()
.load("xxx")
.config(Bitmap.Config.RGB_565)
.into(mImageView);
源码分析
Picasso默认包含七个内置RequestHandler分别用来处理七种不同类型的请求:
ResourceRequestHandler:
用于处理加载图片资源id的情况;ContactsPhotoRequestHandler:
用于处理手机联系人图片;MediaStoreRequestHandler:
用于处理content://media开头的URI;ContentStreamRequestHandler:
用于处理scheme为content的URI;AssetRequestHandler:
用于处理file:///android_asset/开头的URI;FileRequestHandler:
用于处理scheme为file的URI;NetworkRequestHandler:
用于处理http或https图片url;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
---------------------last line for now---------------------