1. 程式人生 > >Android開發圖片快取框架Glide的總結

Android開發圖片快取框架Glide的總結

前言

前段時間寫過一篇圖片快取框架Picasso的用法,對於Picasso有些同學也比較熟悉,採用Lru最近最少快取策略,並且自帶記憶體和硬碟快取機制,在圖片載入尤其是多圖載入著實為大夥省了不少力,在此之前同樣也相識有Afinal、Xutil、UniversalImageLoader等優秀的開源框架,今天再總結一個圖片載入快取框架 — Glide,以助自己後邊的專案構建舔磚加瓦吧。

Glide簡介

Glide是一個快速高效的開源媒體和圖片載入框架,他把媒體解碼、記憶體和磁碟二級快取還有一些資源快取池封裝成一個個簡單的介面,使用很方便,並且Glide也是google推薦使用的圖片載入框架。Glide支援下載、解碼、展示視訊快照和圖片資源以及GIF動畫,Glide支援外掛擴充套件並使用於任何網路網路引擎,預設情況下采用的是HttpUrlconnection網路載入形式,當然也可以採用Google的volley框架和Square的OkHttp來取代。
Glide官方說明:

https://github.com/bumptech/glide

Glide特點

  • 使用簡單
  • 可配置度高,自適應程度高
  • 支援常見圖片格式 Jpg png gif webp
  • 支援多種資料來源 網路、本地、資源、Assets 等
  • 高效快取策略 支援Memory和Disk圖片快取 預設Bitmap格式採用RGB_565記憶體使用至少減少一半
  • 生命週期整合 根據Activity/Fragment生命週期自動管理請求
  • 高效處理Bitmap 使用Bitmap Pool使Bitmap複用,主動呼叫recycle回收需要回收的Bitmap,減小系統回收壓力

Glide和Picasso對比

Glide和Picasso在使用上非常相似,之前也總結過Picasso,發現在某些地方甚至可以完全模仿Picasso寫Glide,不過二者在核心上還是有一定區別的:

  1. Picasso接收的上下文是Context,而Glide傳入的上下文可以有Context、Activity、Fragment。Activity和Fragment有生命週期,因此在某個生命週期階段圖片載入也響應收到控制,更靈活。另外在某些情況下也避免了物件未進行引用而造成的記憶體洩漏問題。
  2. Glide預設的圖片格式RGB565而Picasso支援的圖片格式ARGB8888,儘管前者沒有後者影象更清晰(相差不大),但是在記憶體開銷上卻比前者少了一半,載入更快
  3. Glide預設對圖片快取僅僅是展示控制元件的大小,如果在另外一個不同大小控制元件上載入相同的圖片需要再次下載。Picasso快取的圖片預設是原圖,可對原圖進行隨處展示。
  4. Glide支援媒體解碼,支援GIF動畫載入,Picasso不能。
    Glide和Picasso區別不止以上這些,以上只是些典型的區別。對於Glide的使用,下邊一一道來。

Glide的基礎用法

1.glide專案引用
對於Glide這麼強大的開源框架,又是google推薦的早已加入到jcenter()倉庫中了,所以我們使用的時候只需要在gradle中引用一下倉庫的包即可:

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

2.繫結生命週期,讓Glide載入圖片過程根據生命週期管理。
上邊也提到Glide可以根據多種形式繫結上下文,尤其是針對Activity的引用,可用於在生命週期內對圖片載入進行控制。

 Glide.with(Context context);// 繫結Context
 Glide.with(Activity activity);// 繫結Activity
 Glide.with(FragmentActivity activity);// 繫結FragmentActivity
 Glide.with(Fragment fragment);// 繫結Fragment

3.簡單載入(這裡也可以載入本地和asset,可參考Picasso的簡單用法)。

Glide.with(this).load(imageUrl).into(imageView);

4.設定載入前和載入失敗時的圖片

Glide.with(this).load(imageUrl).placeholder(R.mipmap.ic_launcher).error(R.mipmap.ic_launcher).into(imageView);

5.設定下載優先順序

Glide.with(this).load(imageUrl).priority(Priority.NORMAL).into(imageView);

6.設定記憶體快取(是否進行記憶體快取)

Glide.with(this).load(imageUrl).skipMemoryCache(true).into(imageView);

7.設定磁碟快取

Glide.with(this).load(imageUrl).diskCacheStrategy(DiskCacheStrategy.ALL).into(imageView);

磁碟快取策略說明:

  • ALL:快取源資源和轉換後的資源
  • NONE:不作任何磁碟快取
  • SOURCE:快取源資源
  • RESULT:快取轉換後的資源

8.設定載入動畫
api中預設也存在動畫,這裡可以自己設定,並且也支援屬性動畫

Glide.with(this).load(imageUrl).animate(R.anim.item_alpha_in).into(imageView);

設定淡入動畫

Glide.with(this).load(imageUrl)
.crossFade(1000)        //設定淡入動畫,並且淡入過度時間為1秒
.override(80,80)         //最終呈現的畫素值80*80
.into(imageView3);

9.設定縮圖

Glide.with(this).load(imageUrl).thumbnail(0.1f).into(imageView); //顯示的圖片大小為原圖的1/10

10.設定載入尺寸(畫素)

Glide.with(this).load(imageUrl).override(800, 800).into(imageView);

11.設定圖片適配和轉換
Api提供了centerCrop()、fitCenter()兩種適配方式,前者效果是將圖片按照最小邊充滿,最大邊裁剪適配,後者效果是將圖片按照最大邊充滿最小邊居中空缺適配。

Glide.with(this).load(imageUrl).centerCrop().into(imageView);

也可以自定義Transformation來設定自己的形狀,如設定圓角圖形,圓角半徑單位是dp:

public class GlideRoundTransform extends BitmapTransformation {
        private float radius = 0f;
        public GlideRoundTransform(Context context) {
            this(context, 4);
        }

        public GlideRoundTransform(Context context, int dp) {
            super(context);
            this.radius = Resources.getSystem().getDisplayMetrics().density * dp;
        }

        @Override
        protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
            return roundCrop(pool, toTransform);
        }

        private Bitmap roundCrop(BitmapPool pool, Bitmap source) {
            if (source == null) return null;

            Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
            if (result == null) {
                result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
            }
            Canvas canvas = new Canvas(result);
            Paint paint = new Paint();
            paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
            paint.setAntiAlias(true);
            RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight());
            canvas.drawRoundRect(rectF, radius, radius, paint);
            return result;
        }

        @Override
        public String getId() {
            return getClass().getName() + Math.round(radius);
        }
    }

設定圓角圖片:

Glide.with(this).load(imageUrl).transform(new
GlideRoundTransform(this,100)).into(imageView);

也可以自定義圓形圖片:

public class GlideCircleTransform extends BitmapTransformation {

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

    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        return circleCrop(pool, toTransform);
    }

    private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
        if (source == null) return null;
        //獲取最小邊長
        int size = Math.min(source.getWidth(), source.getHeight());
        //獲取圓形圖片的寬度和高度
        int x = (source.getWidth() - size) / 2;
        int y = (source.getHeight() - size) / 2;

        // TODO this could be acquired from the pool too
        Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);

        Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
        if (result == null) {
            result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
        }

        Canvas canvas = new Canvas(result);
        Paint paint = new Paint();
        paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
        paint.setAntiAlias(true);
        float r = size / 2f;   //得到圓形半徑
        canvas.drawCircle(r, r, r, paint);
        return result;
    }

    @Override
    public String getId() {
        return getClass().getName();
    }
}

設定圓形圖片:

Glide.with(this).load(imageUrl).transform(new GlideCircleTransform(this)).into(imageView);

12.設定要下載的內容
有些時候我們不想直接將載入的圖片顯示到控制元件上,或者我們想下載這張圖片,又或者我們暫時不想在此處展示這張圖片,可以這樣處理:

Glide.with(this).load(imageUrl).centerCrop().into(new SimpleTarget<GlideDrawable>() {
            @Override
            public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
                //這裡可根據resource自行處理(下載...)
            }
        });

13.設定監聽請求介面

Glide.with(this).load(imageUrl).listener(new RequestListener<String, GlideDrawable>() {
            @Override
            public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
                return false;
            }

            @Override
            public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                //imageView.setImageDrawable(resource);
                return false;
            }
        }).into(imageView);

14.設定GIF載入方式

Glide.with(this).load(imageUrl).asBitmap().into(imageView);//顯示gif靜態圖片
Glide.with(this).load(imageUrl).asGif().into(imageView);//顯示gif動態圖片

15.快取動態清理

Glide.get(this).clearDiskCache(); //清理磁碟快取
Glide.get(this).clearMemory(); //清理記憶體快取

Glide的高階用法

Glide內部有一個GlideModule,是用來全域性配置Glide的,可進行設定快取路徑,快取空間,圖片格式,自定義cache指示等操作。

1.GlideModule新增
自定義一個GlideModule :

public class MyGlideModule implements GlideModule {
    @Override public void applyOptions(Context context, GlideBuilder builder) {
        // Apply options to the builder here.
    }

    @Override public void registerComponents(Context context, Glide glide) {
        // register ModelLoaders here.
    }
}

AndroidManifest.xml註冊:

<manifest ...>
    <!-- ... permissions -->
    <application ...>
        <meta-data
            android:name="com.mypackage.MyGlideModule"
            android:value="GlideModule" />
        <!-- ... activities and other components -->
    </application>
</manifest>

混淆處理:

-keepnames class com.mypackage.MyGlideModule
# or more generally:
#-keep public class * implements com.bumptech.glide.module.GlideModule

多個GlideModule衝突問題
一般情況下我們一個專案可以有多個library專案,這樣就可能有多個GlideModule的存在,但是多個GlideModule存在卻會出現衝突,為了避免這種情況發生,一般我們儘量只設置一個GlideModule,當然也可在配置清單中忽略某個GlideMoudle:

<meta-data android:name=”com.mypackage.MyGlideModule” tools:node=”remove” />

2.GlideModule相關配置
設定Glide記憶體快取大小:

int maxMemory = (int) Runtime.getRuntime().maxMemory();//獲取系統分配給應用的總記憶體大小
int memoryCacheSize = maxMemory / 8;//設定圖片記憶體快取佔用八分之一
//設定記憶體快取大小
builder.setMemoryCache(new LruResourceCache(memoryCacheSize));

有些時候我們也需要獲取一下預設的記憶體快取大小:

MemorySizeCalculator calculator = new MemorySizeCalculator(context);  
int defaultMemoryCacheSize = calculator.getMemoryCacheSize();  
int defaultBitmapPoolSize = calculator.getBitmapPoolSize(); 

設定Glide磁碟快取大小和磁碟快取存放位置:

File cacheDir = context.getExternalCacheDir();//指定的是資料的快取地址
int diskCacheSize = 1024 * 1024 * 30;//最多可以快取多少位元組的資料
//設定磁碟快取大小和位置
builder.setDiskCache(new DiskLruCacheFactory(cacheDir.getPath(), "glide", diskCacheSize));

也可以:

//存放在data/data/xxxx/cache/
builder.setDiskCache(new InternalCacheDiskCacheFactory(context, "glide", diskCacheSize));
//存放在外接檔案瀏覽器
builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, "glide", diskCacheSize));

設定圖片解碼格式:
Glide預設的圖片解碼格式是RGB_565相比RGB_8888佔記憶體更小,但是卻損失了一部分圖片質量,需求根據自己定。

//設定圖片解碼格式
builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
//設定BitmapPool記憶體快取大小
builder.setBitmapPool(new LruBitmapPool(memoryCacheSize));

3.使用ModelLoader自定義資料來源:
有些時候我們需要根據不同的情況載入不同格式的圖片,可採用工廠模式來進行選取。

定義處理URL介面

public interface IDataModel {
    String buildDataModelUrl(int width, int height);
}

實現處理URL介面
JpgDataModel:

public class JpgDataModel implements IDataModel {
    private String dataModelUrl;

    public JpgDataModel(String dataModelUrl) {
        this.dataModelUrl = dataModelUrl;
    }

    @Override
    public String buildDataModelUrl(int width, int height) {
        //http://78re52.com1.z0.glb.clouddn.com/resource/gogopher.jpg?imageView2/1/w/200/h/200/format/jpg
        return String.format("%s?imageView2/1/w/%d/h/%d/format/jpg", dataModelUrl, width, height);
    }
}

WebpDataModel:

public class WebpDataModel implements IDataModel {
    private String dataModelUrl;

    public WebpDataModel(String dataModelUrl) {
        this.dataModelUrl = dataModelUrl;
    }

    @Override
    public String buildDataModelUrl(int width, int height) {
        //http://78re52.com1.z0.glb.clouddn.com/resource/gogopher.jpg?imageView2/1/w/200/h/200/format/webp
        return String.format("%s?imageView2/1/w/%d/h/%d/format/webp", dataModelUrl, width, height);
    }
}

設定圖片加工工廠

public class MyDataLoader extends BaseGlideUrlLoader<IDataModel> {
    public MyDataLoader(Context context) {
        super(context);
    }

    public MyDataLoader(ModelLoader<GlideUrl, InputStream> urlLoader) {
        super(urlLoader, null);
    }

    @Override
    protected String getUrl(IDataModel model, int width, int height) {
        return model.buildDataModelUrl(width, height);
    }

    /**
     */
    public static class Factory implements ModelLoaderFactory<IDataModel, InputStream> {

        @Override
        public ModelLoader<IDataModel, InputStream> build(Context context, GenericLoaderFactory factories) {
            return new MyDataLoader(factories.buildModelLoader(GlideUrl.class, InputStream.class));
        }

        @Override
        public void teardown() {
        }
    }
}

根據不同的要求採用不同的策略載入圖片

//載入jpg圖片
Glide.with(this).using(new MyDataLoader(this)).load(new JpgDataModel(imageUrl)).into(imageView);
//載入webp圖片
Glide.with(this).using(new MyDataLoader(this)).load(new WebpDataModel(imageUrl)).into(imageView);

這樣每次載入都要.using(),我們也可以不用.using(),方法就是將MyDataLoader的工廠註冊到GlideModel中:

public class MyGlideModule implements GlideModule {
    ...
    @Override
    public void registerComponents(Context context, Glide glide) {
        glide.register(IDataModel.class, InputStream.class, 
            new MyUrlLoader.Factory());
    }
}

呼叫:

 //載入jpg圖片
 Glide.with(this).load(new JpgDataModel(imageUrl)).into(imageView);
 //載入webp圖片
 Glide.with(this).load(new WebpDataModel(imageUrl)).into(imageView);

以上是個人對Glide的相關總結,Glide功能不止這些,甚或是還可以自定義圖片快取TAG來實現對圖片軟刪除等操作,這些功能在開發中也是微乎其微了,當然Glide開發團隊也是想的周到,以實現程式的健壯性。Glide和Picasso有很多相似之處,瞭解Picasso的同學可以根據Picasso的相關Api很容易上手Glide,返過來也如此,總之後續繼續深入吧。

相關推薦

Android開發圖片快取框架Glide總結

前言 前段時間寫過一篇圖片快取框架Picasso的用法,對於Picasso有些同學也比較熟悉,採用Lru最近最少快取策略,並且自帶記憶體和硬碟快取機制,在圖片載入尤其是多圖載入著實為大夥省了不少力,在此之前同樣也相識有Afinal、Xutil、Univer

Android開發圖片開源框架

2、圖片載入,快取,處理 框架名稱 :Android Universal Image Loader 一個強大的載入,快取,展示圖片的庫,已過時Picasso 一個強大的圖片下載與快取的庫Fresco 一個用於管理影象和他們使用的記憶體的庫Glide 一個圖片載入和快取的庫,使用的App有:網易新聞Glide

Android四大圖片快取框架之-Fresco(一)

本文來自於Fresco中文文件,這僅僅是自己的學習筆記!!!大牛繞路,放我我。 關於Fresco的介紹,請檢視連結 關於android圖片快取,這是一個android程式設計師必須瞭解的。關於四大圖片快取框架的特性與對比,請移步MDCC傳送門 首先說明,本

Android studio 圖片載入框架Glide介紹及使用

在泰國舉行的谷歌開發者論壇上,谷歌為我們介紹了一個名叫 Glide 的圖片載入庫,作者是bumptech。這個庫被廣泛的運用在google的開源專案中,包括2014年google I/O大會上釋出的官方app。 優點: 1,載入速度快 2,使用簡單 3,功能強大 4,記憶體

Android圖片快取的一些總結

最近在做圖片載入時遇到記憶體溢位問題,所以這裡找到一些資料學習後,在這裡做一個總結。 這裡使用帶了LruCache技術和DiskLruCache技術,簡單地說,LruCache是做的記憶體快取處理,只負責記憶體中圖片的管理,也就是在記憶體中快取被清除後還是需要

Android-UIL圖片快取框架 原始碼解析

Android-Universal-Image-Loader 是 github上一個開源的圖片快取框架 ,提供圖片MemoryCache和DiskCache的功能,並支援載入網路、本地、contentProvider圖片的功能 Acceptable URIs examp

圖片載入及快取框架Glide在安卓開發中的應用

注意四種磁碟快取機制 修改Glide預設的網路請求庫 監聽圖片的載入進度 自定義快取的設定 如何清理快取:清理快取:包括清理記憶體快取、清理磁碟快取(開啟子執行緒) 實現圖形轉換(需要自定義類) Glide載入圖片的特點: 優點是比picasso載入的快,使用者體驗比較好

Android圖片載入框架Glide之探究Glide快取機制

轉載自:http://blog.csdn.net/guolin_blog/article/details/54895665 在本系列的上一篇文章中,我帶著大家一起閱讀了一遍Glide的原始碼,初步瞭解了這個強大的圖片載入框架的基本執行流程。 不過,上一篇文

Android 圖片載入框架Glide用法

最近有個需求是,要將 url 地址傳過來的圖片載入到ImageView中,幾番折騰後找到 Glide,真的很好用,所以做下筆記 轉載:https://www.cnblogs.com/guilin-hu/p/5706916.html 在泰國舉行的谷歌開發者論壇上,谷歌為我們介紹了一個名叫&nb

Android中RxJava使用9----自定義圖片快取框架

操作符:concat 不交錯的發射兩個或多個Observable的發射物 原理: 圖片快取框架,原理 1)檢查圖片是否在記憶體中快取 2)如果不在,檢查圖片是否在檔案中快取 3)如果不在,則從網路上拿圖片 下面程式碼只說明原理,真正實現功能,下載原始碼 1、在

Android圖片載入框架Glide用法

轉載地址: 在泰國舉行的谷歌開發者論壇上,谷歌為我們介紹了一個名叫 Glide 的圖片載入庫,作者是bumptech。這個庫被廣泛的運用在google的開源專案中,包括2014年google I/O大會上釋出的官方app。 它的成功讓我非常感興趣。我花了一整晚的時間把

Android開發最新所有框架總結

1. Retrofit   一句話介紹:Retrofit是一款型別安全的網路框架,基於HTTP協議,服務於Android和java語言 上榜理由:Retrofit以21.8k的stars量雄踞github中android子標題榜首,第一當之無愧。 官

Android圖片載入框架Glide的簡單用法

一、概述 Glide是一款由Bump Technologies開發的圖片載入框架,可以在android平臺上以很簡單的方式載入和展示圖片。 目前,Glide最新的穩定版本是3.7.0,這個版本的

android上的一個網路介面和圖片快取框架enif

1.底層網路介面採用apache的httpclient連線池框架; 2.圖片快取採用基於LRU的演算法; 3.網路介面採用監聽者模式; 4.包含圖片的OOM處理(及時回收處理技術的應用);   圖片核心處理類:CacheView.java [java] v

Android 三大圖片載入框架的對比——ImageLoader,Picasso,Glide

一、ImageLaoder介紹    << Universal ImageLoader 是很早開源的圖片快取,在早期被很多應用使用多執行緒下載圖片,圖片可以來源於網路,檔案系統,專案資料夾assets中以及drawable中等支援隨意的配置ImageLoader,

Android圖片載入框架Glide的基本用法

那麼本篇文章是這個系列的第一篇文章,我們先來了解一下Glide的基本用法吧。 開始 Glide是一款由Bump Technologies開發的圖片載入框架,使得我們可以在Android平臺上以極度簡單的方式載入和展示圖片。 目前,Glide最新的穩定版

《轉載》Android圖片載入框架Glide用法

在泰國舉行的谷歌開發者論壇上,谷歌為我們介紹了一個名叫 Glide 的圖片載入庫,作者是bumptech。這個庫被廣泛的運用在google的開源專案中,包括2014年google I/O大會上釋出的官方app。它的成功讓我非常感興趣。我花了一整晚的時間把玩,決定分享一些自己的經驗。在開始之前我想說,Glide

glide圖片載入框架使用總結

<span style="font-family:SimSun; font-size:18px"><span style="line-height:24.05px; background-color:transparent"></span></span><

Android開發常用開源框架圖片處理

1. 圖片載入,快取,處理 框架名稱 功能描述 一個強大的圖片下載與快取的庫 一個用於管理影象和他們使用的記憶體的庫 Glide 一個圖片載入和快取的庫,使用的App有:網易新聞 Andr

修改圖片載入框架Glide快取路徑(可用於清理快取需求)

1.寫一個類實現  GlideModule public class GlideCacheMore implements GlideModule { private String path=Environment.getExternalStorageDirector