第三方庫之—Glide的使用

# Glide的使用

>Glide是我使用最久,也是最喜歡的一款第三方圖片加載框架,以前只是使用,也沒有做系統性的總結,現在開始重新整理一遍這些優秀的第三方框架。

[Glide官方地址:](https://github.com/bumptech/glide)

## Glide的相關方法:

- load():加載資源,String/Uri/File/Integer/URL/byte[]/T,或者 loadFromMediaStore(Uri uri)

- placeholder(resourceId/drawable): 設置資源加載過程中的佔位Drawable。

- error():load失敗時顯示的Drawable。

- override() :調整圖片大小

- centerCrop():圖片裁剪,ImageView 可能會完全填充,但圖像可能不會完整顯示。

- fitCenter(): 圖像裁剪,圖像將會完全顯示,但可能不會填滿整個 ImageView。

- animate(): 指定加載動畫。

- crossFade()/crossFade(int duration):imageView改變時的動畫,version 3.6.1後默認開啟300毫秒

- dontAnimate():移除所有的動畫。

- transform():圖片轉換。

- bitmapTransform(): bitmap轉換,不可以和(centerCrop() 或 fitCenter())共用。

- priority(Priority priority):當前線程的優先級,Priority.IMMEDIATE,Priority.HIGH,Priority.NORMAL(default),Priority.LOW

- thumbnail(): 縮略圖.

- listener():異常監聽

- preload(int width, int height): 預加載resource到緩存中(單位為pixel)

- fallback(Drawable drawable):設置model為空時顯示的Drawable。

- using() :為單個的請求指定一個 model

- asGif():Gif 檢查,如果是圖片且加了判斷,則會顯示error佔位圖,否則會顯示圖片

- asBitmap():bitmap轉化,如果是gif,則會顯示第一幀

- .skipMemoryCache(true) 禁止緩存

- .diskCacheStrategy(DiskCacheStrategy.NONE)禁止磁盤緩存

>Glide 可以以load(File)的形式播放本地視頻,但是如果需要播放網絡視屏,則要用VideoView

---

# 緩存策略

一張圖片變化特別快的時候,應該禁止緩存

```

.skipMemoryCache(true)

```

即使關閉內存緩存,請求圖片將會仍然被存儲在設備的磁盤緩存中,如果一張圖片變化很快,仍需要禁止磁盤緩存

```

.diskCacheStrategy(DiskCacheStrategy.NONE)

```

Glide 緩存了原始圖像,全分辨率圖像和另外小版本的圖像,因此禁用磁盤緩存是用枚舉來控制的

```

DiskCacheStrategy.NONE //什麼都不緩存,就像剛討論的那樣

DiskCacheStrategy.SOURCE //僅僅只緩存原來的全分辨率的圖像。在我們上面的例子中,將會只有一個 1000x1000 像素的圖片

DiskCacheStrategy.RESULT //僅僅緩存最終的圖像,即,降低分辨率後的(或者是轉換後的)

DiskCacheStrategy.ALL //緩存所有版本的圖像(默認行為)

```

## 自定義緩存

磁盤緩存,用類DiskLruCacheWrapper來設置目錄

```

builder.setDiskCache(new DiskCache.Factory() {

@Override

public DiskCache build() {

// 自己的緩存目錄

File imgFile = new File(Environment.getExternalStorageDirectory()+"/Android/data/package-name");

return DiskLruCacheWrapper.get(imgFile,DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE);

}

});

```

內存緩存,用類Memory Cache 來設置大小

```

MemorySizeCalculator calculator = new MemorySizeCalculator(context);

builder.setMemoryCache(new LruResourceCache(calculator.getMemoryCacheSize()));

```

## Bitmap Pool

重複使用及銷燬策略。設置方法:GlideBuilder.setBitmapPool()

默認採用的是LruBitmapPool,使用了LRU算法。

```

MemorySizeCalculator calculator = new MemorySizeCalculator(context);

int defaultBitmapPoolSize = calculator.getBitmapPoolSize();

int customBitmapPoolSize = (int) (1.2 * defaultBitmapPoolSize);

builder.setBitmapPool( new LruBitmapPool( customBitmapPoolSize );

```

## Bitmap Format

Bitmap Format用於設置全局缺省首選Bitmap規格,設置方法:GlideBuilder.setDecodeFormat()

默認採用RGB_565(比ARGB_8888節省一半的內存),但不支持透明度。

# 優先級

會發現優先級高的先 顯示出來,即使圖片比較大。

```

//優先加載

Glide

.with(context)

.load(heroImageUrl)

.priority(Priority.HIGH)

.into(imageViewHero);

//後加載

Glide

.with(context)

.load(itemImageUrl)

.priority(Priority.LOW)

.into(imageViewItem);

```

先顯示縮略圖,後顯示原圖

```

//用原圖的1/10作為縮略圖

Glide

.with(this)

.load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png")

.thumbnail(0.1f)

.into(iv_0);

//用其它圖片作為縮略圖

DrawableRequestBuilder thumbnailRequest = Glide

.with(this)

.load(R.drawable.news);

Glide.with(this)

.load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png")

.thumbnail(thumbnailRequest)

.into(iv_0);

```

# 圖片處理

裁剪、模糊、濾鏡等。可以使用 **wasabeef/glide-transformations** ,

實現Transformation 接口,或者使用抽象類BitmapTransformation,

通過transform()或bitmapTransform()來處理圖片

//圓形裁剪

Glide.with(this)

.load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png")

.bitmapTransform(new CropCircleTransformation(this))

.into(iv_0);

//圓角處理

Glide.with(this)

.load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png")

.bitmapTransform(new RoundedCornersTransformation(this,30,0, RoundedCornersTransformation.CornerType.ALL))

.into(iv_0);

//灰度處理

Glide.with(this)

.load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png")

.bitmapTransform(new GrayscaleTransformation(this))

.into(iv_0);

//模糊處理

Glide.with(this).load(R.drawable.demo)

.bitmapTransform(new BlurTransformation(context))

.into((ImageView) findViewById(R.id.image));

//其它變換...

## 自定義轉換

```

public class BlurTransformation extends BitmapTransformation {

public BlurTransformation(Context context) {

super( context );

}

@Override

protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {

return null; // todo

}

@Override

public String getId() {

return null; // todo

}

}

```

其中getId() :描述了這個轉換的唯一標識符,將作為緩存系統的一部分

可以使用單種轉換和多種轉換,如多種轉換:

```

Glide

.with( context )

.load( eatFoodyImages[1] )

.transform( new GreyscaleTransformation( context ), new BlurTransformation( context ) )

.into( imageView2 );

```

# 回調 Target

SimpleTarget

target 泛型:Bitmap,GlideDrawable,GifDrawable

```

private SimpleTarget target = new SimpleTarget() {

@Override

public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {

// do something with the bitmap

// for demonstration purposes, let's just set it to an ImageView

imageView1.setImageBitmap( bitmap );

}

};

private void loadImageSimpleTarget() {

Glide

.with( context ) // could be an issue!

.load( eatFoodyImages[0] )

.asBitmap()

.into( target );

}

```

## Target生命週期

with( context ):關係到生命週期。如果請求需要在 activity 生命週期之外去做時,需要使用:

```

private void loadImageSimpleTargetApplicationContext() {

Glide

.with( context.getApplicationContext() ) // safer!

.load( eatFoodyImages[1]

.asBitmap()

.into( target2 );

}

```

## Target 指定尺寸

使用ImageView 作為參數給 .into()的時候,Glide 會用 ImageView 的大小去限制圖像的大小

但是target並沒有已知的大小,如果知道圖片大小則應指出,減少內存消耗。

```

private SimpleTarget target2 = new SimpleTarget( 250, 250 ) {

@Override

public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {

imageView2.setImageBitmap( bitmap );

}

};

private void loadImageSimpleTargetApplicationContext() {

Glide

.with( context.getApplicationContext() ) // safer!

.load( eatFoodyImages[1] )

.asBitmap()

.into( target2 );

}

```

## ViewTarget

常用於自定以控件中,比如自定義控件中組合了ImageView控件,如下

public class FutureStudioView extends FrameLayout {

ImageView iv;

TextView tv;

```

public void initialize(Context context) {

inflate( context, R.layout.custom_view_futurestudio, this );

iv = (ImageView) findViewById( R.id.custom_view_image );

tv = (TextView) findViewById( R.id.custom_view_text );

}

public FutureStudioView(Context context, AttributeSet attrs) {

super( context, attrs );

initialize( context );

}

public FutureStudioView(Context context, AttributeSet attrs, int defStyleAttr) {

super( context, attrs, defStyleAttr );

initialize( context );

}

public void setImage(Drawable drawable) {

iv = (ImageView) findViewById( R.id.custom_view_image );

iv.setImageDrawable( drawable );

}

}

```

使用如下方法給自定義控件中的ImageView設置圖片

```

private void loadImageViewTarget() {

FutureStudioView customView = (FutureStudioView) findViewById( R.id.custom_view );

//傳遞了參數 customView

viewTarget = new ViewTarget( customView ) {

@Override

public void onResourceReady(GlideDrawable resource, GlideAnimation super GlideDrawable> glideAnimation) {

//調用了FutureStudioView的setImage方法

this.view.setImage( resource.getCurrent() );

}

};

Glide

.with( context.getApplicationContext() ) // safer!

.load( eatFoodyImages[2] )

.into( viewTarget );

}

```

## NotificationTarget

用於加載圖片到通知欄和應用小部件中的

# 動畫

animate() :可以加載資源文件animate.xml文件

或者 屬性動畫:

- ViewPropertyAnimation

- ViewAnimation

- NoAnimation

- DrawableCrossFadeViewAnimation

```

ViewPropertyAnimation.Animator animationObject = new ViewPropertyAnimation.Animator() {

@Override

public void animate(View view) {

// if it's a custom view class, cast it here

// then find subviews and do the animations

// here, we just use the entire view for the fade animation

view.setAlpha( 0f );

ObjectAnimator fadeAnim = ObjectAnimator.ofFloat( view, "alpha", 0f, 1f );

fadeAnim.setDuration( 2500 );

fadeAnim.start();

}

};

Glide

.with( context )

.load( eatFoodyImages[1] )

.animate( animationObject )

.into( imageView2 );

```

# Glide module

Glide module 是一個抽象方法,全局改變 Glide 行為的一個方式。

前面單策略的定義中都用到了GlideBuilder類

如果你需要訪問 GlideBuilder,你需要去實現一個 GlideModule 接口的公共類

```

public class FileGlideModule implements GlideModule{

@Override

public void applyOptions(final Context context, GlideBuilder builder) {

//builder 內的所有方法你都可以設置。

// builder.setDiskCache(new InternalCacheDiskCacheFactory(context));

builder.setDiskCache(new ExternalCacheDiskCacheFactory(context));

/* builder.setDiskCache(new DiskCache.Factory() {

@Override

public DiskCache build() {

File imgFile = new File(Environment.getExternalStorageDirectory()+"/Android/data/com.leying365");

return DiskLruCacheWrapper.get(imgFile,DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE);

}

});*/

MemorySizeCalculator calculator = new MemorySizeCalculator(context);

builder.setMemoryCache(new LruResourceCache(calculator.getMemoryCacheSize()));

builder.setBitmapPool(new LruBitmapPool(calculator.getBitmapPoolSize()));

builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);

}

@Override

public void registerComponents(Context context, Glide glide) {

}

}

```

最終通過 來生效

常用方法:

- setMemoryCache(MemoryCache memoryCache)

- setBitmapPool(BitmapPool bitmapPool)

- setDiskCache(DiskCache.Factory diskCacheFactory)

- setDiskCacheService(ExecutorService service)

- setResizeService(ExecutorService service)

- setDecodeFormat(DecodeFormat decodeFormat)

# 網絡庫

Glide 使用ModeLoader 接口來 集成網絡庫,Glide提供了兩種網絡庫 的實現,分別為OkHttp 和 Volley。

在build.gradle中添加如下依賴,glide會默認使用OKhttp來做所有的網絡連接

```

dependencies {

// your other dependencies

// ...

// Glide

compile 'com.github.bumptech.glide:glide:3.7.0'

// Glide's OkHttp Integration

compile 'com.squareup.okhttp3:okhttp:3.2.0'

compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'

}

```

上面會將必要的GlideModule 到你的 Android.Manifest中。

## 緩存與失效機制

Glide 通過 url、viewwidth、viewheight、屏幕的分辨率等以一種散列算法生成一個獨有、安全的文件名作為key保存到disk上.因為其是通過一個散列算法來實現的,因此很難定位文件的緩存,幸好Glide提供了signature()方法允許將一個附加的數據加入到緩存key當中,可以用來保證緩存的及時性.

系統默認實現了MediaStoreSignature,StringSignature.

```

Glide.with(fragment)

.load(mediaStoreUri)

.signature(new MediaStoreSignature(mimeType, dateModified, orientation))

.into(view);

```

當然也可以自己來實現Signature

```

public class MSignature implements Key {

@Override

public boolean equals(Object o) {

//...

}

@Override

public int hashCode() {

//...

}

@Override

public void updateDiskCacheKey(MessageDigest messageDigest) {

messageDigest.update(ByteBuffer.allocate(Integer.SIZE)

.putInt(signature).array());

}

}

```

極端情況,不緩存可以用diskCacheStrategy(DiskCacheStrategy.NONE.)來實現

# 圖片下載

Glide除了提供into方法來加載圖片外,也提供了downloadOnly方法來實現圖片下載.

```

FutureTarget future = Glide.with(applicationContext)

.load(yourUrl)

.downloadOnly(500, 500);

File cacheFile = future.get();

```

下載之後可以通過如下方式來加載圖片

```

Glide.with(yourFragment)

.load(yourUrl)

//DiskCacheStrategy.ALL或者DiskCacheStrategy.SOURCE可以保證程序會先去讀緩存文件

.diskCacheStrategy(DiskCacheStrategy.ALL)

.into(yourView);

```

如果想獲取一張圖片的Bitmap,可以使用如下方式

//此方法需要try/catch處理,並且最好在子線程中,否則會阻塞主線程

```

Bitmap myBitmap = Glide.with(applicationContext)

.load(yourUrl)

.asBitmap()

.centerCrop()

//設置大小

.into(500, 500)

.get()

```

# 圖片模糊處理

使用Glide加載圖片,將模糊圖片設置為背景,代碼如下:

```

Glide.with(this).load(mImageCover)

.asBitmap()

.into(new SimpleTarget() {

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)

@Override

public void onResourceReady(Bitmap resource, GlideAnimation super Bitmap> glideAnimation) {

blur(resource,ivCover,24);

ivCover.setImageBitmap(resource);

}

});

```

//blur方法,將圖片模糊處理添加到背景中

```

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)

private void blur(Bitmap bkg, View view, float radius) {

/*view.getMeasuredWidth(),

view.getMeasuredHeight(),*/

Bitmap overlay = Bitmap.createBitmap(

bkg.getWidth(),

bkg.getHeight(),

Bitmap.Config.ARGB_8888);

Canvas canvas = new Canvas(overlay);

canvas.drawBitmap(bkg, -view.getLeft(),

-view.getTop(), null);

RenderScript rs = RenderScript.create(this);

Allocation overlayAlloc = Allocation.createFromBitmap(

rs, overlay);

ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(

rs, overlayAlloc.getElement());

blur.setInput(overlayAlloc);

blur.setRadius(radius);

blur.forEach(overlayAlloc);

overlayAlloc.copyTo(overlay);

view.setBackground(new BitmapDrawable(

getResources(), overlay));

rs.destroy();

}

```

//圖片模糊類,使用方法如下:

```

/*BlurBuilder builder = new BlurBuilder();

Bitmap bitmap = builder.blur(this, bmp);

image.setImageBitmap(bitmap);*/

public class BlurBuilder {

private static final float BITMAP_SCALE = 0.2f;

private static final float BLUR_RADIUS = 8.75f;

public static Bitmap blur(Context context, Bitmap image) {

int width = Math.round(image.getWidth() * BITMAP_SCALE);

int height = Math.round(image.getHeight() * BITMAP_SCALE);

Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);

Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);

RenderScript rs = RenderScript.create(context);

ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));

Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);

Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);

theIntrinsic.setRadius(BLUR_RADIUS);

theIntrinsic.setInput(tmpIn);

theIntrinsic.forEach(tmpOut);

tmpOut.copyTo(outputBitmap);

return outputBitmap;

}

}

```

裁剪、模糊、濾鏡等。可以使用 **wasabeef/glide-transformations**


分享到:


相關文章: