• Picasso 2.71828 用法


    本文基于 Picasso 2.71828 版本 。本文不仅讲用法,更主要讲的是错误的用法。而具体的源码分析在其他文章中。

    implementation 'com.squareup.picasso:picasso:2.71828'

    基本用法

    从 assets 中加载

     Picasso.get()

            .load("file:///android_asset/test_img")

            .into(imageView);

    从资源 Id 中加载图片

    方法一 :

     Picasso.get()

            .load(R.drawable.test_img)

            .into(imageView);

    方法二 :

     Picasso.get()

             .load("android.resource://" + getPackageName() + "/" + R.drawable.test_img)

             .into(imageView);

    从 SD 中加载文件

    File externalFile = getExternalFilesDir(null).getAbsoluteFile();

    File targetFile = new File(externalFile, "test.jpg");

    Picasso.get()

           .load(targetFile)

           .into(imageView);

    从网络中加载图片

    Picasso.get()

           .load("http://i.imgur.com/DvpvklR.png")

           .into(imageView);

    设置占位图

    Picasso.get()

           .load("http://i.imgur.com/DvpvklR.png")

           .placeholder(R.drawable.placeHolder)

           .into(imageView);

    设置加载失败图片

       Picasso.get()

              .load("http://i.imgur.com/DvpvklR.png")

              .error(R.drawable.error_image)

              .into(imageView);

    加载指定大小的图片 :

    例如 : http://i.imgur.com/DvpvklR.png 图片分辨率为 400* 486 ,Bitmap.config 为 ARGB_8888 , 即每个像素占 4 个字节。

    Picasso.get()

           .load("http://i.imgur.com/DvpvklR.png")

           .resize(200,200)

           .into(imageView);

    如果不调用 resize() 方法 , 图片所占用内存大小为 400 * 486 * 4 个字节 。

    调用了 resize() 方法后,图片所占用内存大小为 200 * 200 * 4 个字节。

    可以发现内存占用减少了很多。

    但是请务必注意 , 千万不要以为有了图片加载框架,就可以为所欲为 !!!

    resize() 不仅可以缩小,同时也会放大图片。下面代码 resize()之后 加载了 3500 * 3500 分辨率的图片到内存中。

    所占用内存为 3500 * 3500 * 4 /(1024*1024) = 46.7 M 。如果你的页面存在内存泄露 , 嘿嘿 ,等着加班修 Bug 吧 !

    Picasso.get()

           .load("http://i.imgur.com/DvpvklR.png")

           .resize(3500,3500)

           .into(imageView);

    因此使用 resize 的时候,最好加上 onlyScaleDown() 方法。

    只缩小不放大, 当 resize 尺寸大于 Bitmap 尺寸的时候 ,不放大图片。

    当 resize 尺寸小于 Bitmap 尺寸的时候,缩小图片。

    下面代码最终加载了 400 * 486 分辨率的图片到内存中 。

    Picasso.get()

           .load("http://i.imgur.com/DvpvklR.png")

           .resize(3500,3500)

           .onlyScaleDown()

           .into(imageView);

    设置图片 ScaleType

    以下写法全是错误写法 :

            Picasso.get().load("http://i.imgur.com/DvpvklR.png").centerCrop().into(imageView);

            Picasso.get().load("http://i.imgur.com/DvpvklR.png").centerInside().into(imageView);

            Picasso.get()

                   .centerInside()

                   .centerCrop()

                   .into(imageView);

    centerCrop() 和 centerInside() 单独使用的时候, 必须调用 resize()方法。

    centerCrop() 和 centerInside() 不能同时使用。

    取消加载图片

    当我们退出页面 Activity/fragment 的时候,不想再加载图片,我们需要取消请求。

     Picasso.get().cancelRequest(imageView);

     // 或

     Picasso.get().cancelTag(tag);

    这里大家要注意一下问题 :

    如果正在下载一张图片,你取消了请求,有用吗 ?

    答案: 网络请求不会中断,仍会占用网络继续下载,但是 ImageView 不会收到回调。

    这里的 “正在下载” 的意思是 :

    线程是正在执行 Runnable 方法 。 如果请求在线程池的等待队列当中,那么不会下载 。如果正在执行,则不会中断。

    暂停加载图片

    大家看到暂停加载图片,不要以为是真的支持断点下载。

    这里的暂停加载图片,实际上是取消下载图片。并把当前请求添加到暂停列表中。

    Picasso.get().pauseTag(tag);

    继续加载图片

    这里的继续加载图片,是重新把请求交给 Picasso 来下载,也不是断点下载。

    Picasso.get().resumeTag(tag);

    这个 暂停和继续 下载图片有什么用呢 ? 大多数情况下是用在 ListView/ RecyclerView 当中。

    当快速滑动的时候暂停下载图片,当滑动停止的时候继续加载图片。

    跳过内存缓存加载图片

    有时候不想从内存缓存中加载图片,而想直接从磁盘或网络中加载图片

    我们可以设置其内存策略为 MemoryPolicy.NO_CACHE

            Picasso.get()

                    .load("http://i.imgur.com/DvpvklR.png")

                    .memoryPolicy(MemoryPolicy.NO_CACHE)

                    .into(imageView);

    加载的图片不存放到内存缓存中

    例如我提前知道一张图片分辨率很大,占用的内存很多,因此我不想把这张图片加载到内存中。

    我们可以设置它的内存策略为 MemoryPolicy.NO_STORE 。

         Picasso.get()

                    .load("http://i.imgur.com/DvpvklR.png")

                    .memoryPolicy(MemoryPolicy.NO_STORE)

                    .into(imageView);

    图片加载回调

    注意 ,下面的写法会造成内存泄露 !

            Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(imageView, new Callback() {

                @Override

                public void onSuccess() {

                }

                @Override

                public void onError(Exception e) {

                }

            });

    Callback 匿名内部类持有外部类的引用 。因此在 Activity/Fragment 销毁的时候注意取消请求。

    Picasso.get().cancelRequest(imageView);

    同时注意到, 上边的回调,并没有 Bitmap 对象。 有时候我们需要拿到 Bitmap 对象来做些额外的处理 ,见下:

    图片加载 Bitmap 回调

    注意,下面的写法也是错误的写法

         Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(new Target() {

                @Override

                public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {

                }

                @Override

                public void onBitmapFailed(Exception e, Drawable errorDrawable) {

                }

                @Override

                public void onPrepareLoad(Drawable placeHolderDrawable) {

                }

            });

    在 Picasso 中持有的 ImageView / Target 都是弱引用 , 上面的代码意味着 , Target 随时可能被回收 , 这些回调可能不会被调用。

    正确写法如下 : 将 Target 声明为成员变量, Activity/fragent 销毁的时候要取消请求。

     Picasso.get()

            .load("http://i.imgur.com/DvpvklR.png")

            .into(target);

    ...

        private Target target = new Target() {

            @Override

            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {

            }

            @Override

            public void onBitmapFailed(Exception e, Drawable errorDrawable) {

            }

            @Override

            public void onPrepareLoad(Drawable placeHolderDrawable) {

            }

        };

    ....

       @Override

        protected void onDestroy() {

            super.onDestroy();

            Picasso.get().cancelRequest(target);

        }

    加载图片到内存当中

    有的时候,为了更快的拿到图片,我们需要提前从网络或磁盘中加载图片到内存中。

    例如有两个页面 A、B ,在 A 页面的时候就去下载一张图片,跳转到 B 页面的时候立即显示图片,这样体验更好。

    因此在 A 页面的时候,我们就可以调用。

            Picasso.get()

                   .load("http://i.imgur.com/DvpvklR.png")

                   .fetch();

    如果你需要回调 fetch 方法的回调 : 下面代码同样这是错误的写法 ,理由同上,匿名内部类持有外部类造成的内存泄露 。但是这里 fetch 又不能直接取消。

    这里有两个解决方法。

    1. 设置 tag , 在 Acttivity /fragment 销毁的时候,取消掉 tag 。

    2. 使用 静态内部类 , 如果需要引用 Acttivity /fragment ,请使用弱引用来避免内存泄露。

    3. 不使用 fetch() 方法,使用上述的 into(Target) 方法 。

          Picasso.get().load("http://i.imgur.com/DvpvklR.png").fetch(new Callback() {

                @Override

                public void onSuccess() {

                }

                @Override

                public void onError(Exception e) {

                }

            });

    同步方法获取 Bitmap

    上面获取 Bitmap 对象的方法都是异步方法 ,如果需要同步方法 ,可以调用 get 方法 :

        try {

                Bitmap bitmap = Picasso.get().load("http://i.imgur.com/DvpvklR.png").get();

            } catch (IOException e) {

                e.printStackTrace();

            }

    使用时请务必注意一下两点

    1.get() 方法获取到 Bitmap 后 ,没有存放到内存缓存 ( LruCache )

    原因是 Picasso 不能够保证 Cache 的实现都是线程安全的。

    大家注意一下, Picassso 中的 LruCache 实现了 Cache 接口 , 内部实际调用了 android.util 包下的 LruCache 。

    而 android 的 LruCache 是线程安全的。

    从代码中也可以看出 Picasso 中的 LruCache 方法也是线程安全的。

    而 Picasso 是了为了防止用户 自定义 Cache , 没有保证 set() 和 get() 方法的线程安全。因此才不放到内存缓存当中。

    2. get() 方法不能在主线程调用 ,必须在异步线程中调用 。get() 方法是同步方法 ,会从磁盘或网络中加载图片,是耗时操作。

  • 相关阅读:
    推荐一本SQL经典书籍
    准备升级包包版游戏大厅
    《博客园精华集软件工程分册》第三轮筛选结果
    (翻译)《Expert .NET 2.0 IL Assembler》 第八章 基本类型和签名(一)
    如何输入人名间的顿号
    推荐一个下名人传记电子书的好地方
    asp.net 2.0 中使用web.config存储数据库连接字符串
    Asp.Net小技巧之在client端调用server端事件:
    C#编码好习惯
    把ip转换成对应的城市名
  • 原文地址:https://www.cnblogs.com/endv/p/12249970.html
Copyright © 2020-2023  润新知