Picasso(毕加索)的使用(缓存图片)

时间:2024-02-23 08:08:57
picasso是Square公司开源的一个Android图形缓存库

Picasso不仅实现了图片异步加载的功能,还解决了android中加载图片时需要解决的一些常见问题:

1.在adapter中需要取消已经不在视野范围的ImageView图片资源的加载,否则会导致图片错位,Picasso已经解决了这个问题。

2.使用复杂的图片压缩转换来尽可能的减少内存消耗

3.自带内存和硬盘二级缓存功能

Picasso(毕加索)内部采用了LRUCache类进行内存缓存处理,最大内存分配值为当前手机可用内存的1/7.将近15%。
Picasso的文件缓存,目录在当前的应用的目录下面的picasso-cache这个文件夹下面,默认文件缓存最大不能超过50M,最小不低于5M,
当然,如果当前手机的可用的本地存储小于5M,那么已当前手机的所剩的本地存储的大小作为文件缓存的大小。
使用之前需要添加依赖:
compile \'com.squareup.picasso:picasso:2.5.2\'
1.使用Picasso下载网络图片
 //使用Picasso下载网络图片,当你给一个控件设置了一个fit()方法后,后面就不可以调用resize()方法
 Picasso.with(this).load(url)   //图片地址
             .config(Bitmap.Config.RGB_565)
                .placeholder(R.mipmap.ic_launcher)  //设置占位图,下载图片时显示的
                .error(R.mipmap.ic_launcher) //下载出错显示的图片
                .fit() //控件不能设置成wrap_content,必须有大小fit()才让图片的宽高等于控件的宽高,设置fit(),不能再调用resize()
                .into(imageView); //显示图片的目标控件
2.加载sd卡上的图片
//加载sd卡上的图片,将上面的网址改为file对象就可以了
        File file=new File("路径");
        Picasso.with(this).load(file).config(Bitmap.Config.RGB_565)
                .placeholder(R.mipmap.ic_launcher).error(R.mipmap.ic_launcher).fit().into(imageView);
3.监听Picasso加载图片的结果
//监听Picasso加载图片的结果
        Picasso.with(this).load(url).config(Bitmap.Config.RGB_565)
                .placeholder(R.mipmap.ic_launcher).error(R.mipmap.ic_launcher)
                .fit()
                .into(imageView, new Callback() {
            @Override
            public void onSuccess() {
                Log.i("tag", "图片下载成功,如果是从缓存中获取不会执行");
            }

            @Override
            public void onError() {
                Log.i("tag", "onError: ");
            }
        });

4.将下载的图片变为圆形图片显示

//将下载的图片变为圆形图片显示
        Picasso.with(this).load(url)
                .transform(new CircleTransform()) //转换的方式,可以自定义类实现Transformation接口,重写转换方法就行
                .placeholder(R.mipmap.ic_launcher).error(R.mipmap.ic_launcher)
                .fit().into(imageView);
需要的转换类:
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;

import com.squareup.picasso.Transformation;

/**
 * 将图片转换为圆形,需要实现picasso.Transformation接口
 */
public class CircleTransform implements Transformation {

    @Override   //对Bitmap进行转换操作,需要定义自己的转换方式,都可以重写这个方法
    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;

        //创建一个正方形区域的Btimap
        Bitmap squaredBitmap=Bitmap.createBitmap(source,x,y,size,size);

        if(squaredBitmap!=source){
            source.recycle();
        }

        //创建一张可以操作的正方形图片的位图
        Bitmap bitmap=Bitmap.createBitmap(size,size,source.getConfig());

        //创建一个画布Canvas
        Canvas canvas=new Canvas(bitmap);
        //创建画笔
        Paint paint=new Paint();

        BitmapShader shader=new BitmapShader(squaredBitmap,BitmapShader.TileMode.CLAMP,BitmapShader.TileMode.CLAMP);
        paint.setShader(shader);
        paint.setAntiAlias(true);

        //圆形半径
        float r=size/2f;
        canvas.drawCircle(r,r,r,paint);
        squaredBitmap.recycle();
        return bitmap;
    }

    @Override   //一个key,主要是缓存的key的生成和它有关
    public String key() {
        return "circle";
    }
}

5.滑动ListView停止下载图片的实现:

ListView listView = new ListView(this);
        //在滑动listview时,不会进行图片的加载,停止滑动时,才会继续进行加载图片
        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                final Picasso picasso = Picasso.with(MainActivity.this);
                if (scrollState == SCROLL_STATE_IDLE || scrollState == SCROLL_STATE_TOUCH_SCROLL) {
                    picasso.resumeTag(MainActivity.this);//恢复tag
                } else {
                    picasso.pauseTag(MainActivity.this);//暂停tag
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

            }
        });

6.控制需不需要从缓存中获取图片:

 //1.需求:每次请求网络都是走网络,永远不使用内存缓存和文件缓存
        Picasso.with(this)
                .load("地址")
                .fit()
                .networkPolicy(NetworkPolicy.NO_STORE,NetworkPolicy.NO_CACHE)
                .memoryPolicy(MemoryPolicy.NO_STORE,MemoryPolicy.NO_CACHE)
                .into(imageView);

        //2.需求:每次请求网络,只启用内存缓存,不启用二级缓存文件缓存(DiskCache)
        Picasso.with(this)
                .load("地址")
                .fit()
                .networkPolicy(NetworkPolicy.NO_STORE,NetworkPolicy.NO_CACHE)
                .into(imageView);

        //3.需求:每次请求网络,只启用二级缓存(DiskCache),不启用一级缓存(LRUCache)
        Picasso.with(this)
                .load("地址")
                .fit()
                .memoryPolicy(MemoryPolicy.NO_STORE,MemoryPolicy.NO_CACHE)
                .into(imageView);

        //当然,如果你什么都没有配置,Picasso默认是内存缓存和文件缓存都是启用的。

7.修改缓存位置与调试:

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        initPicasso();
    }

    /**
     * 设置Picasso框架的图片缓存路径,默认在data/data/包名/cache/picasso-cache文件夹下
     * 会报找不到OkHttpDownloader类的异常,这就是不匹配的问题了
     */
    private void initPicasso(){
        String imageCacheDir = Environment.getExternalStorageDirectory()
                .getPath()+ File.separator+"Picasso的缓存路径";
        File cacheFile=new File(imageCacheDir);
        if(!cacheFile.exists()){
            cacheFile.mkdirs();
        }
        Picasso picasso = new Picasso.Builder(this).downloader(new OkHttpDownloader(cacheFile)).build();
        Picasso.setSingletonInstance(picasso);
        /**
         * 这行代码会将你加载的图片的来源通过颜色的方式在图片的左上角有展示:
         * 红色:代表从网络下载的图片
         * 黄色:代表从磁盘缓存加载的图片
         * 绿色:代表从内存缓存中加载的图片
         */
        Picasso.with(this).setIndicatorsEnabled(true);
    }

}