Android圖片加載框架Picasso最全使用教程 四

  通過前幾篇的學習,我們已經對Picasso的加載圖片的用法有了很深的瞭解,接下來我們開始分析Picasso爲我們提供的其他高級功能及內存分析,Let’s Go !

Picasso進行圖片的旋轉(Rotation)

簡單的旋轉,只需要增加一個角度即可,調用rotate(float degrees)

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

Picasso
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .rotate(90f) //旋轉90.into(imageViewSimpleRotate);

根據某個點進行復雜的旋轉操作

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

Picasso
    .with(context)
    .load(R.drawable.floorplan)
    .rotate(45f, 200f, 100f)
    .into(imageViewComplexRotate);

對圖片的轉化(Transformation)

模糊一張圖片

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

public class BlurTransformation implements Transformation {

    RenderScript rs;

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

    @Override
    public Bitmap transform(Bitmap bitmap) {
        // 創建一個Bitmap作爲最後處理的效果Bitmap
        Bitmap blurredBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);

        // 分配內存
        Allocation input = Allocation.createFromBitmap(rs, blurredBitmap, Allocation.MipmapControl.MIPMAP_FULL, Allocation.USAGE_SHARED);
        Allocation output = Allocation.createTyped(rs, input.getType());

        // 根據我們想使用的配置加載一個實例
        ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
        script.setInput(input);

        // 設置模糊半徑
        script.setRadius(10);

        //開始操作
        script.forEach(output);

        // 將結果copy到blurredBitmap中
        output.copyTo(blurredBitmap);

        //釋放資源
        bitmap.recycle();

        return blurredBitmap;
    }

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

//然後調用即可

Picasso
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .transform(new BlurTransformation(context))
    .into(imageViewTransformationBlur);

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

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

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

public class GrayscaleTransformation implements Transformation {

    private final Picasso picasso;

    public GrayscaleTransformation(Picasso picasso) {
        this.picasso = picasso;
    }

    @Override
    public Bitmap transform(Bitmap source) {
        Bitmap result = createBitmap(source.getWidth(), source.getHeight(), source.getConfig());
        Bitmap noise;
        try {
            noise = picasso.load(R.drawable.noise).get();
        } catch (IOException e) {
            throw new RuntimeException("Failed to apply transformation! Missing resource.");
        }

        BitmapShader shader = new BitmapShader(noise, REPEAT, REPEAT);

        ColorMatrix colorMatrix = new ColorMatrix();
        colorMatrix.setSaturation(0);
        ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);

        Paint paint = new Paint(ANTI_ALIAS_FLAG);
        paint.setColorFilter(filter);

        Canvas canvas = new Canvas(result);
        canvas.drawBitmap(source, 0, 0, paint);

        paint.setColorFilter(null);
        paint.setShader(shader);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));

        canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint);

        source.recycle();
        noise.recycle();

        return result;
    }

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

//下面進行調用

List<Transformation> transformations = new ArrayList<>();

transformations.add(new GrayscaleTransformation(Picasso.with(context)));
transformations.add(new BlurTransformation(context));

Picasso
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .transform(transformations)
    .into(imageViewTransformationsMultiple);

這個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就不會在內存及本地進行緩存了

代碼示例:

Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[1])
    .memoryPolicy(MemoryPolicy.NO_CACHE)
    .into(imageViewFromDisk);

當然,你也可以這樣調用:

Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[1])
    .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
    .into(imageViewFromDisk);

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

NetworkPolicy

就像MemoryPolicy負責管理內存緩存一樣,NetworkPolicy就是負責管理本地緩存的,而且二者的用法一模一樣,NetworkPolicy也是一個枚舉,不過它有三個值:

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

示例代碼:

Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[2])
    .networkPolicy(NetworkPolicy.NO_CACHE)
    .into(imageViewFromNetwork);

當然,你也可以配合MemoryPolicy一起使用

Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[2])
    .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
    .networkPolicy(NetworkPolicy.NO_CACHE)
    .into(imageViewFromNetwork); 

查看圖片都來源於何處,緩存指示器

作爲一個有經驗的猿猿,我們肯定想知道我們所加載的圖片來源於何處,是內存,本地還是從網絡加載的,當然這個動作Picasso已經爲我們想好了,我們只需要在請求的時候調用.setIndicatorsEnabled(true);就行了,代碼:

Picasso  
    .with(context)
    .setIndicatorsEnabled(true);

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

  • 藍色 - 從內存中獲取,是最佳性能展示
  • 綠色 - 從本地獲取,性能一般
  • 紅色 - 從網絡加載,性能最差

查看圖片加載用時

緩存指示器能幫助我們查看圖片的加載來源,但是並不能精確的知道每張圖片從網絡加載時所用的時間,在請求開始我們就加上調用.setLoggingEnabled(true),來通過輸出日誌的方式查看每張網絡請求的資源所用的時間; 上代碼:

Picasso  
    .with(context)
    .setLoggingEnabled(true);

Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[2])
    .memoryPolicy(MemoryPolicy.NO_CACHE)
    .networkPolicy(NetworkPolicy.NO_CACHE)
    .into(imageViewFromNetwork);

然後通過在控制檯上查看日誌信息,如下:

D/Picasso﹕ Main        created      [R0] Request{http://i.imgur.com/rT5vXE1.jpg}  
D/Picasso﹕ Dispatcher  enqueued     [R0]+21ms  
D/Picasso﹕ Hunter      executing    [R0]+26ms  
D/Picasso﹕ Hunter      decoded      [R0]+575ms  
D/Picasso﹕ Dispatcher  batched      [R0]+576ms for completion  
D/Picasso﹕ Main        completed    [R0]+807ms from NETWORK  
D/Picasso﹕ Dispatcher  delivered    [R0]+809ms  

整體加載分析StatsSnapshot

你可能有一個場景,需要看一個大圖的加載在內存中佔用了多大,你可以調用StatsSnapshot即可,代碼:


StatsSnapshot picassoStats = Picasso.with(context).getSnapshot();  
//然後打印
Log.d("Picasso Stats", picassoStats.toString()); 

最後輸出結果爲:


D/Picasso Stats﹕ StatsSnapshot{
maxSize=28760941, 
size=26567204, 
cacheHits=30, 
cacheMisses=58, 
downloadCount=0, 
totalDownloadSize=0, 
averageDownloadSize=0, 
totalOriginalBitmapSize=118399432, 
totalTransformedBitmapSize=96928004, 
averageOriginalBitmapSize=2466654, 
averageTransformedBitmapSize=2019333, 
originalBitmapCount=48, 
transformedBitmapCount=41, 
timeStamp=1432576918067}

OK,到此關於Picasso的高級用法我們都有了一定得了解,後面我們將介紹Picasso.Builder來改變Picasso的實例,願大家都有一個美好的一天.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章