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() 方法是同步方法 ,會從磁盤或網絡中加載圖片,是耗時操作。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM