Glide 知識梳理(3) 自定義transform

澤毛發表於2017-12-21

一、概述

有時候,當我們去伺服器請求圖片資源成功之後,希望先對它進行一些處理,例如縮放、旋轉、蒙灰等,然後再把處理後的圖片展示在控制元件上,這時候就可以用上Glide提供的transform()方法,簡單來說,transform()的作用就是改變原始資源在客戶端上最終的展現結果

二、示例

2.1 採用BitmapTransformation進行變換

首先,transform(xxx)接收的引數型別有兩種,一種是BitmapTransformation,另一種是Transformtion<GifBitmapWrapper>,下面是它們的定義,在平時的使用過程中,如果我們的資源為靜態圖片,而不是Gif或者Media,那麼通過繼承BitmapTransformation來實現自己的變換就可以了。

    //接收BitmapTransformation作為引數.
    public DrawableRequestBuilder<ModelType> transform(BitmapTransformation... transformations) {
        return bitmapTransform(transformations);
    }
    //接收Transformation作為引數.
    @Override
    public DrawableRequestBuilder<ModelType> transform(Transformation<GifBitmapWrapper>... transformation) {
        super.transform(transformation);
        return this;
    }
複製程式碼

下面,我們就以一下簡單的例子,來看一下如何使用BitmapTransformation來改變圖片的展示結果。 這裡的變換用到了前面介紹過的setShader相關的知識,可以參考下面這篇文章:

http://www.jianshu.com/p/6ab058329ca8

首先,定義自己的BitmapTransformation實現:

    private class MyBitmapTransformation extends BitmapTransformation {

        public MyBitmapTransformation(Context context) {
            super(context);
        }

        @Override
        protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
            Canvas canvas = new Canvas(toTransform);
            BitmapShader bitmapShader = new BitmapShader(toTransform, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            int min = Math.min(toTransform.getWidth(), toTransform.getHeight());
            int radius = min / 2;
            RadialGradient radialGradient = new RadialGradient(toTransform.getWidth() / 2 , toTransform.getHeight() / 2, radius, Color.TRANSPARENT, Color.WHITE, Shader.TileMode.CLAMP);
            ComposeShader composeShader = new ComposeShader(bitmapShader, radialGradient, PorterDuff.Mode.SRC_OVER);
            Paint paint = new Paint();
            paint.setShader(composeShader);
            canvas.drawRect(0, 0, toTransform.getWidth(), toTransform.getHeight(), paint);
            return toTransform;
        }

        @Override
        public String getId() {
            return "MyBitmapTransformation";
        }
    }
複製程式碼

得到了BitmapTransform之後,通過下面的方式來載入圖片資源,並傳入我們定義的Transformation

    public void loadTransform(View view) {
        MyBitmapTransformation myBitmapTransformation = new MyBitmapTransformation(this);
        Glide.with(this)
                .load("http://i.imgur.com/DvpvklR.png")
                .diskCacheStrategy(DiskCacheStrategy.NONE)
                .transform(myBitmapTransformation)
                .into(mImageView);
    }
複製程式碼

最終得到的結果如下圖所示:

Glide 知識梳理(3)   自定義transform

2.2 使用多個BitmapTransformation

從上面的定義中,可以看到transform接收的引數個數是可變,也就是說,我們可以傳入多個Transformation進行組合,它們會按順序應用到最終的影像上。

三、方法說明

看完上面的應用之後,我們去原始碼中看一下各方法的說明。

3.1 Transformation<T>

BitmapTransformation是實現了Transformation<T>介面的抽象類,原始碼當中對於Transformation的描述是:

/**
 * A class for performing an arbitrary transformation on a resource.
 *
 * @param <T> The type of the resource being transformed.
 */
複製程式碼

BitmapTransform的引數T就是Bitmap,也就是說它是用來給Bitmap進行變換,Transformation定義了兩個介面:

  • Resource<T> transform(Resource<T> resource, int outWidth, int outHeight) resourceget方法會返回原始資源,它可能是從伺服器上面下載的圖片,也可能是上一個transformation變換後的資源,而返回值就是經過變化後的resource,而outWidth/outHeight就是我們所要載入到的目標Target的寬高,在上面的例子中,就是ImageView所指定的寬高。
  • String getId() 前面在介紹基礎使用的文章當中,我們說過最終快取的資原始檔的Cache key會依賴於一些因素,這個getId方法的返回值就是其中的一個因素。

3.2 BitmapTransformation

BitmapTransformation是實現了Transformation的抽象類,它實現了transform(Resource<T> resource, int outWidth, int outHeight)這個方法,並在裡面呼叫了下面這個方法讓子類去實現,也就是我們例子中實現的抽象方法,這主要是方便我們通過BitmapPoolBitmap物件進行復用,同時使用者只用關心需要變換的BitmapBitmapTransformation會負責把它更新回原來的Resource物件中。

protected abstract Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight);
複製程式碼

對於這個方法的實現,有幾個需要注意的點:

  • 對於傳入的toTransform Bitmap,不要去回收它或者把它放入到快取池。如果實現者返回了一個不同的Bitmap例項,Glide會負責去回收或者複用toTransform這個Bitmap
  • 不要去回收作為這個方法返回值的bitmap
  • 如果在這個方法的執行過程中產生了臨時的Bitmap例項,那麼最好把它放入快取池,或者回收它。

相關文章