Android中图片加载框架Picasso的使用

时间:2022-06-26 15:30:47

编写不易,如有转载,请声明出处: 梦回河口:http://blog.csdn.net/zxc514257857/article/details/71430300

技术要点

  • 基本显示(异步加载,图片压缩,图片缓存)
  • 加载中和加载错误的图片显示
  • 设置图片尺寸(Resize)、缩放(Scale)和裁剪(Crop)
  • 图片旋转
  • 设置转换器
  • 取消默认的内存缓存
  • 设置缓存指示器
  • 请求优先级设置
  • 图片还未加载出来时取消Picasso的请求
  • 其它扩展功能

Demo展示图片

Android中图片加载框架Picasso的使用

布局代码

//(layout)activity_main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.test.picassodemo.activity.MainActivity">


<ImageView
android:id="@+id/imageView1"
android:layout_weight="1"
android:layout_margin="10dp"
android:layout_width="match_parent"
android:layout_height="0dp"/>


<ImageView
android:id="@+id/imageView2"
android:layout_weight="1"
android:layout_margin="10dp"
android:layout_width="match_parent"
android:layout_height="0dp"/>


</LinearLayout>
----------------------------------------------------------------------------------------
//(menu)main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/fromInternet"
android:showAsAction="never"
android:title="fromInternet"/>


<item
android:id="@+id/fromUri"
android:showAsAction="never"
android:title="fromUri"/>


<item
android:id="@+id/fromFile"
android:showAsAction="never"
android:title="fromFile"/>


<item
android:id="@+id/fromResourse"
android:showAsAction="never"
android:title="fromResourse"/>


<item
android:id="@+id/noFade"
android:showAsAction="never"
android:title="noFade"/>


<item
android:id="@+id/reSize"
android:showAsAction="never"
android:title="reSize"/>


<item
android:id="@+id/transformation1"
android:showAsAction="never"
android:title="transformation1"/>


<item
android:id="@+id/transformation2"
android:showAsAction="never"
android:title="transformation2"/>


<item
android:id="@+id/transformation3"
android:showAsAction="never"
android:title="transformation3"/>


<item
android:id="@+id/transformation4"
android:showAsAction="never"
android:title="transformation4"/>


<item
android:id="@+id/cache"
android:showAsAction="never"
android:title="cache"/>


<item
android:id="@+id/indicator"
android:showAsAction="never"
android:title="indicator"/>

</menu>
----------------------------------------------------------------------------------------
//(values)dimens
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="image_width">200dp</dimen>
<dimen name="image_height">200dp</dimen>
----------------------------------------------------------------------------------------

activity代码

  注:不要忘了设置网络权限

    <uses-permission android:name="android.permission.INTERNET"/>

  添加Gradle依赖

    compile 'com.squareup.picasso:picasso:2.5.2'
//(activity)MainActivity
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import com.squareup.picasso.MemoryPolicy;
import com.squareup.picasso.NetworkPolicy;
import com.squareup.picasso.Picasso;
import com.test.picassodemo.R;
import com.test.picassodemo.transformation.BlurTransformation;
import com.test.picassodemo.transformation.CircleImageTransformation;
import com.test.picassodemo.transformation.CropSquareTransformation;
import com.test.picassodemo.transformation.GrayTransformation;
import com.test.picassodemo.transformation.RoundTransformation;

public class MainActivity extends AppCompatActivity {
private Context mContext = MainActivity.this;
private ImageView mImageView1;
private ImageView mImageView2;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}

private void initView(){
mImageView1 = (ImageView) findViewById(R.id.imageView1);
mImageView2 = (ImageView) findViewById(R.id.imageView2);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main,menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.fromInternet:
// fromInterNet 默认是异步加载
// placeholder和error通常在网络加载中使用
// placeholder提供一张在网络请求还没有完成时显示的图片,它必须是本地图片
// error提供一张在加载图片出错的情况下显示的默认图片,它必须是本地图片
Picasso.with(mContext)
.load("http://img1.3lian.com/2015/w2/52/d/102.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
.centerCrop()
.fit()
// 设置请求的优先级 高,默认是正常
.priority(Picasso.Priority.HIGH)
// 设置Tag,可以在退出界面,图片还未加载出来时取消Picasso的请求
.tag("photoTag")
.into(mImageView1);

Picasso.with(mContext)
.load("http://img1.3lian.com/2015/w2/52/d/105.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
.centerCrop()
.fit()
// 设置请求的优先级 低,默认是正常
.priority(Picasso.Priority.LOW)
// 设置Tag,可以在退出界面,图片还未加载出来时取消Picasso的请求
.tag("photoTag")
.into(mImageView2);
break;

case R.id.noFade:
// fromInterNet 默认是异步加载
// noFade 取消渐入过度效果
Picasso.with(mContext)
.load("http://img2.3lian.com/2014/c7/12/d/77.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
.noFade()
.tag("photoTag")
.into(mImageView1);

Picasso.with(mContext)
.load("http://img2.3lian.com/2014/c7/12/d/82.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
.noFade()
.tag("photoTag")
.into(mImageView2);
break;

case R.id.reSize:
// fromInterNet 默认是异步加载
// reSize 设置图片尺寸
Picasso.with(mContext)
.load("http://img1.3lian.com/2015/a1/110/d/13.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
// 使用dp设置图片宽高
.resizeDimen(R.dimen.image_width,R.dimen.image_height)
// 使用px设置图片宽高
// .resizeDimen(400,200)
// 只有当原始图片的尺寸大于我们指定的尺寸时,resize才起作用
.onlyScaleDown()
// 以(pivotX, pivotY)为原点旋转
.rotate(180,200,100)
.tag("photoTag")
.into(mImageView1);

Picasso.with(mContext)
.load("http://img1.3lian.com/2015/a1/110/d/11.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
// 使用dp设置图片宽高
.resizeDimen(R.dimen.image_width,R.dimen.image_height)
// 使用px设置图片宽高
// .resizeDimen(400,200)
// 只有当原始图片的尺寸大于我们指定的尺寸时,resize才起作用
.onlyScaleDown()
// 以(pivotX, pivotY)为原点旋转
.rotate(180,200,100)
.tag("photoTag")
.into(mImageView2);
break;

case R.id.fromUri:
// fromUri
break;

case R.id.fromFile:
// fromFile
break;

case R.id.fromResourse:
// fromResourse
Picasso.with(mContext).load(R.mipmap.pic1).into(mImageView1);
Picasso.with(mContext).load(R.mipmap.pic2).into(mImageView2);
break;

case R.id.transformation1:
// 对图片进行高斯模糊、添加圆角、度灰、圆形图片等处理
// 高斯模糊
Picasso.with(mContext)
.load("http://img1.3lian.com/2015/a1/110/d/12.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
.centerCrop()
.fit()
.transform(new BlurTransformation(mContext))
.tag("photoTag")
.into(mImageView1);

// 度灰处理
Picasso.with(mContext)
.load("http://img1.3lian.com/2015/a1/110/d/15.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
.centerCrop()
.fit()
.transform(new GrayTransformation())
.tag("photoTag")
.into(mImageView2);
break;

case R.id.transformation2:
// 对图片进行高斯模糊、添加圆角、度灰、圆形图片等处理
// 圆角处理
Picasso.with(mContext)
.load("http://img1.3lian.com/2015/a1/120/d/120.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
.centerCrop()
.fit()
.transform(new RoundTransformation(30))
.tag("photoTag")
.into(mImageView1);

// 圆形遮罩处理
Picasso.with(mContext)
.load("http://img1.3lian.com/2015/a1/120/d/122.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
.centerCrop()
.fit()
.transform(new CircleImageTransformation())
.tag("photoTag")
.into(mImageView2);
break;

case R.id.transformation3:
// 对图片进行高斯模糊、添加圆角、度灰、圆形图片等处理
// 方形图片
Picasso.with(mContext)
.load("http://img1.3lian.com/2015/a2/58/d/146.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
.centerCrop()
.fit()
.transform(new CropSquareTransformation())
.tag("photoTag")
.into(mImageView1);
break;

case R.id.transformation4:
// 对图片进行高斯模糊、添加圆角、度灰、圆形图片等处理
// 混合处理(添加圆角、度灰处理)
Picasso.with(mContext)
.load("http://img1.3lian.com/2015/a2/58/d/146.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
.centerCrop()
.fit()
// 有些还是不能一起使用 比如圆角和灰度一起使用没效果
// 灰度和圆形遮罩一起使用 显示外围边框线
// .transform(new GrayTransformation())
.transform(new RoundTransformation(100))
.transform(new BlurTransformation(mContext))
.tag("photoTag")
.into(mImageView1);

// 混合处理(添加高斯模糊、圆形遮罩处理)
Picasso.with(mContext)
.load("http://img1.3lian.com/2015/a2/58/d/151.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
.centerCrop()
.fit()
.transform(new BlurTransformation(mContext))
.transform(new CircleImageTransformation())
.tag("photoTag")
.into(mImageView2);
break;

case R.id.cache:
// 默认内存缓存和磁盘缓存都开启,图片保存于内存中容易OOM,取消内存缓存
Picasso.with(mContext)
.load("http://img1.3lian.com/2015/w2/53/d/8.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
.centerCrop()
.fit()
// 设置请求的优先级 高,默认是正常
.priority(Picasso.Priority.HIGH)
// 设置Tag,可以在退出界面,图片还未加载出来时取消Picasso的请求
//跳过内存缓存
.memoryPolicy(MemoryPolicy.NO_CACHE,MemoryPolicy.NO_STORE)
//跳过磁盘缓存
.networkPolicy(NetworkPolicy.NO_CACHE)
.tag("photoTag")
.into(mImageView1);

// 默认内存缓存和磁盘缓存都开启,图片保存于内存中容易OOM,取消内存缓存
Picasso.with(mContext)
.load("http://img1.3lian.com/2015/w2/53/d/5.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
.centerCrop()
.fit()
// 设置请求的优先级 高,默认是正常
.priority(Picasso.Priority.HIGH)
// 设置Tag,可以在退出界面,图片还未加载出来时取消Picasso的请求
//强制从缓存获取结果
.networkPolicy(NetworkPolicy.OFFLINE)
.tag("photoTag")
.into(mImageView2);
break;

case R.id.indicator:
// 打开缓存指示器 true为打开
// 红色表示网络加载 蓝色表示磁盘加载 绿色表示缓存加载
Picasso.with(mContext).setIndicatorsEnabled(true);

Picasso.with(mContext)
.load("http://img1.3lian.com/2015/w2/53/d/2.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
.centerCrop()
.fit()
.tag("photoTag")
.into(mImageView1);

Picasso.with(mContext)
.load("http://img1.3lian.com/2015/w2/53/d/6.jpg")
.placeholder(R.mipmap.loading)
.error(R.mipmap.error)
.centerCrop()
.fit()
.tag("photoTag")
.into(mImageView2);

break;

default:
break;
}
return super.onOptionsItemSelected(item);
}

@Override
protected void onDestroy() {
// 设置Tag,可以在退出界面,图片还未加载出来时取消Picasso的请求
Picasso.with(mContext).cancelTag("PhotoTag");
super.onDestroy();
}
}

transformation代码

//(transformation)BlurTransformation
import android.content.Context;
import android.graphics.Bitmap;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import com.squareup.picasso.Transformation;

/**
* 高斯模糊处理
*/

public class BlurTransformation implements Transformation{
RenderScript rs;
public BlurTransformation(Context context) {
super();
rs = RenderScript.create(context);
}

@Override
public Bitmap transform(Bitmap bitmap) {
// Create another bitmap that will hold the results of the filter.
Bitmap blurredBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);

// Allocate memory for Renderscript to work with
Allocation input = Allocation.createFromBitmap(rs, blurredBitmap, Allocation.MipmapControl.MIPMAP_FULL, Allocation.USAGE_SHARED);
Allocation output = Allocation.createTyped(rs, input.getType());

// Load up an instance of the specific script that we want to use.
ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
script.setInput(input);

// Set the blur radius
script.setRadius(25);

// Start the ScriptIntrinisicBlur
script.forEach(output);

// Copy the output to the blurred bitmap
output.copyTo(blurredBitmap);

bitmap.recycle();

return blurredBitmap;
}

@Override
public String key() {
return "blur";
}
}
----------------------------------------------------------------------------------------
//(transformation)CircleImageTransformation
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import com.squareup.picasso.Transformation;

/**
* 圆形遮罩处理
*/

public class CircleImageTransformation implements Transformation{

@Override
public Bitmap transform(Bitmap source) {
int minEdge = Math.min(source.getWidth(), source.getHeight());
int dx = (source.getWidth() - minEdge) / 2;
int dy = (source.getHeight() - minEdge) / 2;

// Init shader
Shader shader = new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Matrix matrix = new Matrix();
matrix.setTranslate(-dx, -dy); // Move the target area to center of the source bitmap
shader.setLocalMatrix(matrix);

// Init paint
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setShader(shader);

// Create and draw circle bitmap
Bitmap output = Bitmap.createBitmap(minEdge, minEdge, source.getConfig());
Canvas canvas = new Canvas(output);
canvas.drawOval(new RectF(0, 0, minEdge, minEdge), paint);

// Recycle the source bitmap, because we already generate a new one
source.recycle();

return output;
}

@Override
public String key() {
return "circleImage";
}
}
----------------------------------------------------------------------------------------
//(transformation)CropSquareTransformation
import android.graphics.Bitmap;
import com.squareup.picasso.Transformation;

/**
* 正方形切割
*/

public class CropSquareTransformation implements 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";
}
}
----------------------------------------------------------------------------------------
//(transformation)GrayTransformation
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import com.squareup.picasso.Transformation;

/**
* 灰度处理
*/

public class GrayTransformation implements Transformation{

@Override
public Bitmap transform(Bitmap source) {
int width, height;
height = source.getHeight();
width = source.getWidth();

Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(source, 0, 0, paint);

if(source!=null && source!=bmpGrayscale){
source.recycle();
}
return bmpGrayscale;
}

@Override
public String key() {
return "gray";
}
}
----------------------------------------------------------------------------------------
//(transformation)RoundTransformation
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import com.squareup.picasso.Transformation;

/**
* 圆角处理
*/

public class RoundTransformation implements Transformation {
private int radius;//圆角值

public RoundTransformation(int radius) {
this.radius = radius;
}

@Override
public Bitmap transform(Bitmap source) {
int width = source.getWidth();
int height = source.getHeight();
//画板
Bitmap bitmap = Bitmap.createBitmap(width, height, source.getConfig());
Paint paint = new Paint();
Canvas canvas = new Canvas(bitmap);//创建同尺寸的画布
paint.setAntiAlias(true);//画笔抗锯齿
paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
//画圆角背景
RectF rectF = new RectF(new Rect(0, 0, width, height));//赋值
canvas.drawRoundRect(rectF, radius, radius, paint);//画圆角矩形
//
paint.setFilterBitmap(true);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(source, 0, 0, paint);
source.recycle();//释放

return bitmap;
}

@Override
public String key() {
return "round";
}
}

参考资料

  picasso-强大的Android图片下载缓存库:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0731/1639.html

  图片加载框架-Picasso最详细的使用指南:http://www.jianshu.com/p/c68a3b9ca07a

  Picasso 源码流程分析:http://blog.qiji.tech/archives/10948?utm_source=tuicool&utm_medium=referral

Demo下载请移步:http://download.csdn.net/detail/zxc514257857/9836779


———-因本人才疏学浅,如博客或Demo中有错误的地方请大家随意指出,与大家一起讨论,共同进步,谢谢!———-