1. 程式人生 > >Android圖片載入框架Picasso使用教程 (四)

Android圖片載入框架Picasso使用教程 (四)

通過前幾篇的學習,我們已經對Picasso的載入圖片的用法有了很深的瞭解,接下來我們開始分析Picasso為我們提供的其他高階功能及記憶體分析,Let’s Go ! (ps:想要獲取更多學習資料可加qq1692250804!)      Picasso進行圖片的旋轉(Rotation)
     簡單的旋轉,只需要增加一個角度即可,呼叫rotate(float degrees)

    當我們對一張圖片需要進行簡單的旋轉處理時,只需要呼叫傳入旋轉的角度,大於0小於360即可,上程式碼:


  1. <font color="rgb(85, 85, 85)">Picasso
  2.     .with(context)
  3.     .load(UsageExampleListViewAdapter.eatFoodyImages[0])
  4.     .rotate(90f) //旋轉90度
  5.     .into(imageViewSimpleRotate);</font>
複製程式碼
       根據某個點進行復雜的旋轉操作

      因為圖片的旋轉都是相對(0,0)進行操作,所以如果我們想自定義相對於某個點,也是可以的,只需要呼叫
.rotate(float degrees, float pivotX, float pivotY)


  1. <font color="rgb(85, 85, 85)">Picasso
  2.     .with(context)
  3.     .load(R.drawable.floorplan)
  4.     .rotate(45f, 200f, 100f)
  5.     .into(imageViewComplexRotate);</font>
複製程式碼
       對圖片的轉化(Transformation)

      模糊一張圖片

      我們可以在一張圖片進行展示之前,對其進行操作,然後在展示;這時我們需要定義一個類實現Transformation,然後重寫裡面重要的方法,直接上程式碼:


  1. <font color="rgb(85, 85, 85)">public class BlurTransformation implements Transformation {
  2.     RenderScript rs;
  3.     public BlurTransformation(Context context) {
  4.         super();
  5.         rs = RenderScript.create(context);
  6.     }
  7.     @Override
  8.     public Bitmap transform(Bitmap bitmap) {
  9.         // 建立一個Bitmap作為最後處理的效果Bitmap
  10.         Bitmap blurredBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
  11.         // 分配記憶體
  12.         Allocation input = Allocation.createFromBitmap(rs, blurredBitmap, Allocation.MipmapControl.MIPMAP_FULL, Allocation.USAGE_SHARED);
  13.         Allocation output = Allocation.createTyped(rs, input.getType());
  14.         // 根據我們想使用的配置載入一個例項
  15.         ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
  16.         script.setInput(input);
  17.         // 設定模糊半徑
  18.         script.setRadius(10);
  19.         //開始操作
  20.         script.forEach(output);
  21.         // 將結果copy到blurredBitmap中
  22.         output.copyTo(blurredBitmap);
  23.         //釋放資源
  24.         bitmap.recycle();
  25.         return blurredBitmap;
  26.     }
  27.     @Override
  28.     public String key() {
  29.         return "blur";
  30.     }
  31. }
  32. //然後呼叫即可
  33. Picasso
  34.     .with(context)
  35.     .load(UsageExampleListViewAdapter.eatFoodyImages[0])
  36.     .transform(new BlurTransformation(context))
  37.     .into(imageViewTransformationBlur);</font>
複製程式碼

       在圖片被載入之前就會被我們先處理一遍;

      對載入的資源進行復雜的操作(模糊+縮放)

       我們應該注意到,Picasso給我們提供了一個這樣的API,允許我們將引數設定為一個Transformations的集合
       transform(List<? extends Transformation> transformations),這就意味著我們可以對資源進行一系列的操作;上程式碼:


  1. <font color="rgb(85, 85, 85)">public class GrayscaleTransformation implements Transformation {
  2.     private final Picasso picasso;
  3.     public GrayscaleTransformation(Picasso picasso) {
  4.         this.picasso = picasso;
  5.     }
  6.     @Override
  7.     public Bitmap transform(Bitmap source) {
  8.         Bitmap result = createBitmap(source.getWidth(), source.getHeight(), source.getConfig());
  9.         Bitmap noise;
  10.         try {
  11.             noise = picasso.load(R.drawable.noise).get();
  12.         } catch (IOException e) {
  13.             throw new RuntimeException("Failed to apply transformation! Missing resource.");
  14.         }
  15.         BitmapShader shader = new BitmapShader(noise, REPEAT, REPEAT);
  16.         ColorMatrix colorMatrix = new ColorMatrix();
  17.         colorMatrix.setSaturation(0);
  18.         ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);
  19.         Paint paint = new Paint(ANTI_ALIAS_FLAG);
  20.         paint.setColorFilter(filter);
  21.         Canvas canvas = new Canvas(result);
  22.         canvas.drawBitmap(source, 0, 0, paint);
  23.         paint.setColorFilter(null);
  24.         paint.setShader(shader);
  25.         paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
  26.         canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint);
  27.         source.recycle();
  28.         noise.recycle();
  29.         return result;
  30.     }
  31.     @Override
  32.     public String key() {
  33.         return "grayscaleTransformation()";
  34.     }
  35. }
  36. //下面進行呼叫
  37. List<Transformation> transformations = new ArrayList<>();
  38. transformations.add(new GrayscaleTransformation(Picasso.with(context)));
  39. transformations.add(new BlurTransformation(context));
  40. Picasso
  41.     .with(context)
  42.     .load(UsageExampleListViewAdapter.eatFoodyImages[0])
  43.     .transform(transformations)
  44.     .into(imageViewTransformationsMultiple);</font>
複製程式碼

        這個transformations我相信已經能夠給你足夠強大的功能供你處理圖片資源,到這裡,Picasso基本所有的高階功能都被你所掌握了,已經非常好了,           下面我們就開始分析Picasso的快取元件,讓我們繼續揭開Picasso的神祕面紗;

      關於快取機制

        Picasso預設的快取分配大小特點:

  • LRU快取佔應用程式可用記憶體的15%
  • 本地快取佔到硬碟空間的2%但不超過50M並且不小於5M(前提是這種情況只在4.0以上有效果,或者你能像OKHttp那樣提供一個本地快取庫來支援全平臺)
  • Picasso預設開啟3個執行緒來進行本地與網路之間的訪問
  • Picasso載入圖片順序, 記憶體–>本地–>網路

       Memory Policy

      可能有的時候你不想讓Picasso去記憶體中進行讀取而跳過此步驟,這時你可以在進行網路請求時呼叫memoryPolicy(MemoryPolicy policy,                     MemoryPolicy... additional),MemoryPolicy是一個列舉,只有兩個值 NO_CACHE 和 ‘NO_STORE`

  • NO_CACHE - 讓Picasso跳過從記憶體中讀取圖片這一操作
  • NO_STORE - 如果你的圖片只加載一次就沒用了,就呼叫該值,這樣的話Picasso就不會在記憶體及本地進行快取了

      程式碼示例:


  1. <font color="rgb(85, 85, 85)">Picasso  
  2.     .with(context)
  3.     .load(UsageExampleListViewAdapter.eatFoodyImages[1])
  4.     .memoryPolicy(MemoryPolicy.NO_CACHE)
  5.     .into(imageViewFromDisk);</font>
複製程式碼
       當然,你也可以這樣呼叫:

  1. <font color="rgb(85, 85, 85)">Picasso  
  2.     .with(context)
  3.     .load(UsageExampleListViewAdapter.eatFoodyImages[1])
  4.     .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
  5.     .into(imageViewFromDisk);</font>
複製程式碼

       注意:呼叫.memoryPolicy(MemoryPolicy.NO_CACHE)雖然能避免Picasso從記憶體中讀取資源,但是並不能避免從本地讀取資源,如果你也想跳過從本地讀取這一過程,請看NetworkPolicy.

      NetworkPolicy

      就像MemoryPolicy負責管理記憶體快取一樣,NetworkPolicy就是負責管理本地快取的,而且二者的用法一模一樣,NetworkPolicy也是一個列舉,不過它有三個值:

  • NO_CACHE - 讓Picasso跳過從本地讀取資源這一過程
  • NO_STORE - 讓Picasso不進行本地圖片快取
  • OFFLINE - 讓Picasso載入圖片的時候只從本地讀取除非聯網正常並且本地找不到資源的情況下

      示例程式碼:


  1. <font color="rgb(85, 85, 85)">Picasso  
  2.     .with(context)
  3.     .load(UsageExampleListViewAdapter.eatFoodyImages[2])
  4.     .networkPolicy(NetworkPolicy.NO_CACHE)
  5.     .into(imageViewFromNetwork);</font>
複製程式碼       當然,你也可以配合MemoryPolicy一起使用

  1. <font color="rgb(85, 85, 85)">Picasso  
  2.     .with(context)
  3.     .load(UsageExampleListViewAdapter.eatFoodyImages[2])
  4.     .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
  5.     .networkPolicy(NetworkPolicy.NO_CACHE)
  6.     .into(imageViewFromNetwork); </font>
複製程式碼

       檢視圖片都來源於何處,快取指示器

        作為一個有經驗的猿猿,我們肯定想知道我們所載入的圖片來源於何處,是記憶體,本地還是從網路載入的,當然這個動作Picasso已經為我們想好了,我們只需要在請求的時候呼叫.setIndicatorsEnabled(true);就行了,程式碼:


  1. <font color="rgb(85, 85, 85)">Picasso  
  2.     .with(context)
  3.     .setIndicatorsEnabled(true);</font>
複製程式碼

       這樣每張圖片在顯示的時候,左上角都會有一個小標記,分別又三種三色,藍色,綠色,紅色;

  • 藍色 - 從記憶體中獲取,是最佳效能展示
  • 綠色 - 從本地獲取,效能一般
  • 紅色 - 從網路載入,效能最差


      檢視圖片載入用時

       快取指示器能幫助我們檢視圖片的載入來源,但是並不能精確的知道每張圖片從網路載入時所用的時間,在請求開始我們就加上呼叫.setLoggingEnabled(true),來通過輸出日誌的方式檢視每張網路請求的資源所用的時間; 上程式碼:


  1. <font color="rgb(85, 85, 85)">Picasso  
  2.     .with(context)
  3.     .setLoggingEnabled(true);
  4. Picasso  
  5.     .with(context)
  6.     .load(UsageExampleListViewAdapter.eatFoodyImages[2])
  7.     .memoryPolicy(MemoryPolicy.NO_CACHE)
  8.     .networkPolicy(NetworkPolicy.NO_CACHE)
  9.     .into(imageViewFromNetwork);</font>
複製程式碼
       然後通過在控制檯上檢視日誌資訊,如下:


  1. <font color="rgb(85, 85, 85)">D/Picasso﹕ Main        created      [R0] Request{http://i.imgur.com/rT5vXE1.jpg}  
  2. D/Picasso﹕ Dispatcher  enqueued     [R0]+21ms  
  3. D/Picasso﹕ Hunter      executing    [R0]+26ms  
  4. D/Picasso﹕ Hunter      decoded      [R0]+575ms  
  5. D/Picasso﹕ Dispatcher  batched      [R0]+576ms for completion  
  6. D/Picasso﹕ Main        completed    [R0]+807ms from NETWORK  
  7. D/Picasso﹕ Dispatcher  delivered    [R0]+809ms  </font>
複製程式碼

      整體載入分析StatsSnapshot

       你可能有一個場景,需要看一個大圖的載入在記憶體中佔用了多大,你可以呼叫StatsSnapshot即可,程式碼:


  1. <font color="rgb(85, 85, 85)">
  2. StatsSnapshot picassoStats = Picasso.with(context).getSnapshot();  
  3. //然後列印
  4. Log.d("Picasso Stats", picassoStats.toString());</font>
複製程式碼        最後輸出結果為:

  1. <font color="rgb(85, 85, 85)">
  2. D/Picasso Stats﹕ StatsSnapshot{
  3. maxSize=28760941,
  4. size=26567204,
  5. cacheHits=30,
  6. cacheMisses=58,
  7. downloadCount=0,
  8. totalDownloadSize=0,
  9. averageDownloadSize=0,
  10. totalOriginalBitmapSize=118399432,
  11. totalTransformedBitmapSize=96928004,
  12. averageOriginalBitmapSize=2466654,
  13. averageTransformedBitmapSize=2019333,
  14. originalBitmapCount=48,
  15. transformedBitmapCount=41,
  16. timeStamp=1432576918067}</font>
複製程式碼        OK,到此關於Picasso的高階用法我們都有了一定得了解,後面我們將介紹Picasso.Builder來改變Picasso的例項,願大家都有一個美好的一天.