版權宣告:
本賬號釋出文章均來自公眾號,承香墨影(cxmyDev),版權歸承香墨影所有。
每週會統一更新到掘金,如果喜歡,可關注公眾號獲取最新文章。
未經允許,不得轉載。
一、前言
Glide 現在大範圍的使用在各種商業專案中,而對於一般而言, Glide 的 Api 封裝的非常好,多數情況下我們只需要使用它,在使用的基礎之上,才考慮如何瞭解它。
本文的目的是讓你如何快速上手 Glide 3.x ,來快速投入開發,本文力求做到快速上手,所以只講在上手的時候,你需要關注的。
本文最開始只是想做一個簡短的快速上手的教程,但是在寫的過程中,越寫越長。但是內容都是我覺得必須要講清楚的,所以如果想要快速上手 Glide,請耐心閱讀。
二、簡單使用
2.1 什麼是 Glide ?
既然要用到 Glide ,那就先簡單的介紹一下 Glide 。
Glide 簡單來說就是一個 Google 主導的圖片載入開源庫。它穩定、速度快、可自適應圖片尺寸、支援眾多格式、支援載入不同來源的圖片、記憶體和磁碟快取的優化。這些,都是它的好處(當然不止這些),這裡就不一一細說了。
你只需要知道,它是一款主流的圖片載入庫即可,它包含了你能想到的所有功能,並且支援擴充套件。
Glide 的 Github 地址:
2.2 在專案內整合 Glide
雖然它已經到 v4.x 了,但是本文還是就最常用的 v3.8.0 版本的整合,做一個簡單的介紹。
整合的方式有多種,可以直接引用 jar 包,也可以使用 Maven,這裡還是使用主流的 Gradle 來整合它。
如果需要配置混淆,還需要在混淆檔案中區分 Glide 。
Glide 只是一個圖片載入庫,而大多數情況下,我們的圖片均來自網際網路。所以它的網路請求庫,其實是可以配置的,Glide 可以支援 OkHttp 和 Volley 。
這裡使用的另外一個優秀的網路請求庫 OkHttp 來做支援。
配好 Glide ,我們就可以開始使用它了。
2.3 最簡單的使用
Glide 是支援鏈式呼叫的,但是它不是簡單的在每個方法中,返回 this ,它更復雜一些,後面會講到,所以通常使用它只需要使用一條語句即可。
這是一個最簡單的 Glide 的 Demo,使用它即可從網路上載入一張圖片到一個 ImageView 中去顯示。
三、Glide 需要了解的內容
前面的例子可以看到,實際上 Glide 的鏈式呼叫,它的主要方法就是三個,先來簡單看看他們.
- with : 主要是傳遞一個 Glide 可用的 Context,它和生命週期相關。
- load:接收一個待載入的圖片資源,可支援多種格式。
- into;指定載入的圖片的最終使用目標物件,例如可以是一個 ImageView。
這三個主要的部分,貫穿了 Glide 使用的主要重點內容,接下來讓我們好好看看他們。
3.1 with()
前面提到,這裡的 with()
方法用於給 Glide 傳遞一個 Context 物件,它可以支援多種 Context。
對於 with 而言,它會返回一個 RequestManager 用於管理請求,而它接收的這些不同的 Context ,並不是為了讓我們方便使用,而是會對當前 Context 的生命週期做監聽,來管理 Glide 自身的圖片載入的請求。
舉個例子:當使用 with(Activity
) 的時候,如果此時當前 Activity 被關閉掉了,那麼 Glide 就會將這個 Activity 下所有的圖片請求停止掉。也就是實現了 Glide 和 頁面宣告週期的繫結,來優化 Glide 自身的請求策略。
所以,在使用 Glide 的時候,儘量使用當前頁面的 Activity ,而非直接傳遞一個 Context 進去。儘量小的選擇 Context 的範圍,他們的推薦優先順序為:
Fragment > Activity > Context
3.2 load()
load()
方法,就是去指定一個待載入的資源,它支援很多格式和資源種類。例如:網路地址、本地檔案、Drawable 等,它都是可以做到很好的載入的。
load()
方法,並不是在 Glide 中,前面也提到 with()
會返回一個 RequestManager 物件,load()
方法在它內部實現。
具體 load()
方法,支援的資源種類,可以看到它方法的過載,基本上我們能想到的,它都支援。
有意思的是 load()
方法,它返回的是另外一個 DrawableTypeRequest 物件。
3.3 into()
into()
方法,用於指定載入的圖片資源,最終給誰來使用。這個沒什麼好說的,載入的圖片,最終一定是用來顯示的,所以它需要指定一個使用圖片的物件。
into()
實際上是 DrawableTypeRequest 中的方法,DrawableTypeRequest 是一個多層繼承的類,它實際上自己是沒有對 into()
方法的實現的,大部分實現都是在其父類 DrawableRequestBuilder 和 父類的父類 GenericRequestBuilder 中的,但是這並不影響我們使用它。
從方法的簽名,可以看到 into()
不只是可以接受一個 ImageView ,也可以是一些其他的什麼。這也很好理解,在專案內,也不僅僅只有 ImageView 可以用來顯示圖片,View 的 background 也是可以用於顯示圖片的。
除了 ImageView 前面已經介紹過了,直接使用即可。剩下的後面會有講到。
四、Glide 的使用細節
既然 Glide 使用過程中,最重要的三個方法已經介紹過了,他們是 Glide 能完成功能的基礎,接下來,就開始介紹 Glide 的使用細節,來見證 Glide 的強大。
本節介紹的 Glide 的使用細節,基本上都是與 load()
方法返回的 DrawableTypeRequest 物件進行操作,對其進行一些配置。
4.1 不同狀態的佔點陣圖
在圖片載入的過程中,會經歷過多過程,例如:載入中、載入失敗等等,在這些過程中,其實是可以為暫時為 ImageView 設定一個佔位的的,來定製載入中、載入失敗這種狀態的顯示效果。
Glide 定製的佔點陣圖,有三種:
- placeholder :指定載入前顯示的圖片資源。
- error:指定載入失敗顯示的圖片資源。
- fallback:指定傳遞載入資源為 null 的時候,顯示的圖片資源。
例如上面的例子中,其實 fallback()
是無需指定的,因為 imageUri 是不可能為 null 的。而其他的,都會在不同的階段顯示出來,載入前會顯示 load_placeholder ,如果載入失敗了,會顯示 load_error 。
注意,不同狀態的佔點陣圖,實際上是一種容錯的表現,所以只能用於載入一個『本地資源』,允許傳遞一個 @DrawableId 或者 Drawable 物件。
4.2 縮放控制
某些時候,因為圖片的尺寸和控制元件的尺寸,不一定能匹配,所以會對圖片的顯示效果,進行一些縮放,而大多數情況下,這種預設的縮放策略,並不是我們想要的。
Glide 提供了一些方法來控制縮放的效果。
- centerCrop()
- fitCenter()
這兩個方法和 ImageView.setScaleType() 中傳遞的引數效果類似,就不再一一贅述了。
4.3 快取控制
現在基本上所有的圖片載入庫,都是遵照三級快取的策略:網路、磁碟、記憶體。Glide 也是如此,並且預設情況下,為了更好的體驗,這些快取都是全部開啟的。
就 Glide 的快取策略而言,其實我們也是有辦法去調整的。
對於記憶體快取而言,只有有或者沒有的情況,所以 Glide 只提供了一個 skipMemoryCache()
方法,它可以傳遞一個 Boolean 的值,用於指定是否跳過磁碟快取,預設情況下是 false ,表示需要記憶體快取。
但是對於磁碟快取,就會更復雜一些。Glide 為了保證效率,實際上預設情況下是會去快取多種尺寸的圖片在磁碟上的,也就是說,對於同一個 Uri,如果你在不同尺寸的 ImageView 中使用到它了,預設情況下,在你裝置的磁碟上,也會有多張不同尺寸的圖片。這樣是為了下次載入的時候,速度更快,無需再對原圖進行處理,是一種以空間換效率的策略。
而如果我們需要對磁碟快取進行調節,就需要使用 diskCacheStrategy()
方法來改變它,前面提到它是一種比較複雜的策略,所以無法簡單的使用一個 Boolean 值就完成了。它需要傳遞一個 DiskCacheStrategy 的列舉型別。
可以看到,它實際上是通過兩個引數來標記磁碟快取的策略的。
- ALL:快取所有型別的圖片(預設行為)。
- NONE :禁用磁碟快取。
- SOURCE : 只快取全尺寸的原圖。
- RESULT :只快取壓縮後的圖片。
所以具體使用那種,就需要看當前載入的圖片屬於哪一種了。
上面的例子就是忽略記憶體快取,並且磁碟只快取原圖的策略。
4.4 載入優先順序
對於同一個頁面,如果需要在多個地方都載入線上圖片,必然會存在一個優先順序的問題。例如:正常來說,背景圖是比其他圖片優先順序更高的圖片。
Glide 是可以在載入中,對當前載入的圖片,調整載入的優先順序的。需要使用 priority()
方法,它可以接受一個 Priority 的列舉型別,包含四種值:LOW(低)、HIGH(高)、NORMAL(普通)、IMMEDIATE(立即)。
可以在我們需要的時候,對其進行配置,但是它並不影響用 Glide 載入的圖片的顯示順序,只是用於 Glide 在載入圖片的時候一個優化請求的引數而已,並不影響最終顯示的順序。
4.5 載入動畫
Glide 在顯示圖片的時候,為了讓顯示效果不那麼突兀,會以一種更柔和的方式去顯示,就會在載入的時候給一個動畫效果,它可以使用 crossFade()
方法進行配置,如果不特殊處理,預設它是開啟的,並且本身預設動畫的時長是 300ms。
crossFade()
也是有多個過載的,主要是為了指定動畫以及動畫的時長。如果有心,也可以看看 crossFade()
的原始碼,它實際上只是對 animate()
方法的一個包裝而已,後面會講到。
而 crossFade()
的效果是預設開啟的,所以如果我們不需要這樣的一個動畫效果,可以使用 dontAnimate()
來禁用動畫效果。
有一些情況下,crossFade()
方法並不能滿足我們的需求。如果對載入的動畫有特殊的定製需要,可以使用更靈活的 animate()
方法來自己實現動畫。
可以看到,animate()
支援多種格式的動畫的配置,對於動畫的效果,這裡就不一一講解了。
4.6 支援 Gif & 視訊
Glide 的一個非常棒的功能,就是可以支援 Gif,並且使用起來和正常的想要載入一張網路上的圖片,並沒有什麼區別。
上面的例子中,會在 mBgImageView 中顯示 Gif 圖的效果,並且自動播放,並且可以在載入前為其設定一個佔點陣圖,這些都和載入一個普通的圖片沒有什麼區別。
但是有時候我們需要對載入的 Gif 圖做一個檢查,例如校驗它是否是一個 Gif ,如果不是,則認為是一次錯誤的載入。這個時候就可以使用 asGif()
來進行校驗,如果當前載入的圖片不是一個正確的 Gif 格式,則會去顯示 error()
配置的圖片。
當然,有時候我們可能只是為了顯示一張圖片,可以強制顯示 Gif 圖片的第一幀,使用 asBitmap()
方法標記即可。
只需要將 asGif()
替換成 asBitmap()
就餓可以了,這裡不再單獨提供示例了。
Glide 對 Gif 的支援之外,提示還對 Video 格式的檔案也進行了支援。但是它和 Gif 顯示的效果不一樣的一點在於,它並不會去播放視訊檔案,而只是將視訊檔案的第一幀做為一個圖片去顯示出來。如果依然想要播放一段視訊檔案,使用 Glide 不是一個好注意,你應該使用 VideoView。
其次 Glide 對視訊的支援,僅限於本地視訊,並無法對網路視訊進行支援。
4.7 載入監聽
如果有對 Glide 載入的圖片的結果進行監聽的,可以使用 listener()
方法設定一個監聽器,它接收一個 RequestListener 的介面
一般而言,如果我們需要監聽圖片載入錯誤的原因,可以在 onException()
中做處理。
需要注意的是,這兩個方法的返回值,最好都是 false,因為如果返回 true ,將表示你已經處理了這次的事件,而 Glide 將不會再做額外的處理。例如,如果 onException()
返回了 true 的話,在圖片載入失敗之後,error()
中設定的圖片,並不會被顯示,因為 Glide 認為開發者已經在外部對這個錯誤進行了處理。
4.8 變換載入的圖片
對於使用 Glide 載入的圖片,如果想要在其顯示之前,對其進行一些變換操作,例如,改變顏色、虛化、圓角子類的,都需要用到 transfrom()
方法,它主要用於支援在圖片顯示之前,自定義的變換效果。
變換有兩個方法:
- transfrom():它可以新增一個通用的變換效果。
- bitmapTransfrom():限制了變換的型別,只能設定 Bitmap 的變換。
變換這種操作,其實定製性非常的強,展開講就比較複雜了,大家只需要知道,Glide 是可以對載入的圖片在顯示之前進行一些預處理的操作的,在具體使用的時候再回頭來看相關資料即可。
這裡推薦一個開源的庫,來支援大多數變換的效果。
Github 地址:
4.9 into() 其他實現
前面所有的例子中,into()
方法作為 Glide 載入圖片流程的最後一個環節,它不僅僅只能支援一個 ImageView。有時候我們還需要給 View 中設定一個背景的需要,這個使用 Glide 也是可以辦到的,但是就需要用到 into()
方法的其他過載方法了。
撇開 into(ImageView) 不說,into(int,int) 實際上是一個指定尺寸的同步方法,可以在子執行緒中,通過它來得到一個 GlideDrawable 物件。
但是這並不是很常用的場景,大部分我們還是使用泛型的方式來使用 Glide 的。
它的完整簽名可以看出,它實際上接收的是一個 Target 物件,而 Glide 同時也提供了非常多的 Target 的子類。
這些子類裡面,有一些是不常用的,例如 AppWidgetTarget 和 NotificationTarget 就是為了 AppWidget 和 Notification 中載入圖片準備的。這裡只介紹兩個比較常用的 Target :SimpleTarget 和 ViewTarget ,其實使用起來都是大同小異。
如果我們不關心圖片載入的用途,只是單純的需要載入一個 Bitmap 或者 Drawable ,就可以使用 SimpleTarget 來處理。
SimpleTarget 可以接受一個 GlideDrawable 或者 Bitmap 的型別作為載入的型別。如果需要指定載入的圖片尺寸,還可以在構造方法中指定,如果不對其進行指定,則載入的是圖片的原尺寸。
再來看看 ViewTarget, 從名稱上可以才出來,它實際上是想讓 Glide 載入一個圖片資源給某個 View 使用。它可以解決有時候我們顯示圖片的 View 並不是一個 ImageView 的問題,也可能是一個 View 的背景。
ViewTarget 需要指定 View 的型別,以及載入的資源型別,這裡直接使用的 View 和 GlideDrawable ,然後將我們需要的使用圖片的目標 View 當構造引數傳遞進去即可,最終它它會一個內部 view 變數去持有它,供之後使用。
在 onResourceReady() 這個回撥方法中,直接按我們的需要使用 GlideDrawable 和 View 即可。
如果是需要在非 ImageView 的其他 View 上使用圖片,推薦使用 ViewTarget 。它內部是會去計算 View 的尺寸,來優化快取的圖片。和載入 ImageView 的效果是一樣的,如果使用 SimpleTarget 就需要考慮到 View 的尺寸問題了。
在使用 Target 的時候,還有一點需要額外注意的。
前面也提到,Glide 此次載入的圖片生命週期,會和 with() 傳遞進去的 Context 的生命週期進行繫結,所以使用 Target 載入圖片的時候,就需要額外注意了,如果不是和頁面繫結的圖片資源,可以使用 ApplicationContext() ,避免當前頁面被銷燬之後,載入的請求也被停止了。
五、小結
本文最開始只是想要做一個適合初學者快速上手的 Glide 使用手冊,但是越寫越長,讀到這裡相信你也能有所收穫,之後如果覺得有寫概念也需要初學者瞭解,會繼續補充。