# Android筆記--Glide Glide 是一個開源的 Android 圖像加載庫,用於在應用程式中高效地顯示圖像。它提供了一種簡單、直觀的 API 來載入、緩存和顯示圖像。Glide 旨在快速、高效且可擴展,並且可以與各種圖像來源一起使用,包括本地檔案、URL 和內容提供者。 - **非同步圖像載入**:可以==在後台線程上載入圖像,從而避免阻塞 UI 緒程==。 這可以提高應用程式的響應速度並減少卡頓。 - **多種圖像來源**:==可以從多種來源載入圖像,包括本機檔案、URL 和內容提供者==。 - **圖像轉換**:提供了各種圖像轉換,例如縮放、裁剪和圓形化、、旋轉、模糊等。 可以輕鬆地自定義圖像的外觀。 - **簡單的 API**:提供了簡單、直觀的 API,易於使用。 - **自適應**:能夠自動適應 ImageView 的大小來載入和顯示圖片,無需手動調整尺寸。 - **記憶體和磁碟快取**:==具有靈活的記憶體和磁碟快取策略,可以幫助減少網路請求次數==,加快圖片載入速度,並在應用程式運行期間有效地管理記憶體和磁碟快取。 - **載入動畫**:==支援載入轉場動畫==,可以在圖片載入完成前顯示佔位圖或載入動畫,提升使用者體驗。 - **生命週期管理**:Glide 與 Activity 和 Fragment 的生命週期綁定,==能夠自動管理圖片載入任務,避免在應用程式退出或 Activity 銷毀時發生記憶體洩漏==。 --- ▼※啟用※ --- ### 1.啟用Glide插件 到[Maven](https://mvnrepository.com/)尋找Glide的載入指令後放到build.gradle.kts(Module:app)的dependencies裡 :::success :::spoiler ※===圖片步驟===※ ![image](https://hackmd.io/_uploads/BJMJHLigR.png) ::: :::success :::spoiler ※===參考資料===※ - [9.關於dependencies的一些常識。](https://hackmd.io/AH4zJw6BTJSMoWN8i0dY5A#9%E9%97%9C%E6%96%BCdependencies%E7%9A%84%E4%B8%80%E4%BA%9B%E5%B8%B8%E8%AD%98%E3%80%82) - [Android筆記–Room(本篇的範例使用KAPT)--啟用](https://hackmd.io/kD5kTSH1T-a9yKoJlXRLxA?both#%E2%96%BC%E2%80%BB%E5%95%9F%E7%94%A8%E2%80%BB) - [Maven--Glide](https://mvnrepository.com/artifact/com.github.bumptech.glide/glide) ::: ### 2.宣告網路使用許可權(非必要) 如果想要加載的是網路的圖片,需要在AndroidManifest.xml中額外宣告網路許可權(如果是使用本地的圖片就不用) :::success ``` <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS\_NETWORK\_STATE"/> ``` ![image](https://hackmd.io/_uploads/HyEFD8oeC.png) ::: --- ▼※基本使用※ ---- Glide基本三件套: - with(context):上下文,除了context,還可以放View、fragment、fragmentActivity。 - load(url): 圖片來源,如果加載的是本地圖片,那就使用`R.xxx`的位置。 - into(imageView): 要把圖片放到哪裡去,通常是imageView。 ``` var url = "https://pbs.twimg.com/media/GCzdwECXsAEMj13?format=jpg&name=900x900" Glide.with(context).load(url).into(imageView) ``` --- ▼※一些其他的設定(1)※ --- ==**這些設定,必須寫在`load()`之後、`into()`之前(也就是load和into之間),不然無法使用。**== ### **◆ override()**: 變更圖片大小。 :::success - :::spoiler ※===override()介紹===※ - 單位為像素(px),可以填入一個(size)或兩個參數(height和Width) - 備註:override在imageView大小固定的情況下(例如:RecyclerView),由於圖像框大小是固定的,因此實際呈現效果會變成調整解析度。 - ![image](https://hackmd.io/_uploads/r1nx6j2lA.png) ::: ### **◆ priority()**: 圖片載入的優先級(多個圖片載入時使用) :::info - :::spoiler ※===priority()介紹===※ - 內部需填入一個priority參數,分四個級別,IMMEDIATE(即刻)、HEIGHT(高)、NORMAL(正常)、LOW(低) - ![image](https://hackmd.io/_uploads/HkyJijngR.png) ::: ### **◆ error()**: 如果load()的圖像載入失敗時,會調用此方法中的方法、圖片 :::success - :::spoiler ※===error()介紹===※ - **內部需要填入一個圖片來源或方法** - **==在error()中放入一個"哭哭貓"圖片==** ![image](https://hackmd.io/_uploads/SyYbe3nxA.png)![image](https://hackmd.io/_uploads/Hyb1Gh2xA.png) - **==在error()中放入一個Toast==** ![image](https://hackmd.io/_uploads/HyLBfh3eC.png)![image](https://hackmd.io/_uploads/Hyh_fnneA.png) - **==密技: 如果同時想要錯誤圖片和錯誤訊息,要把圖片的error()寫在Toast的Error()之前,如果相反則只會顯示Toast==** - ![image](https://hackmd.io/_uploads/r18Ho3hgC.png)![image](https://hackmd.io/_uploads/rkvZjh3eA.png) ::: ### **◆ circleCrop()**: 將載入的圖片裁切為圓形形狀。 :::info - :::spoiler ※===circleCrop()介紹===※ - ![image](https://hackmd.io/_uploads/ryL97MRxR.png) - 此方法只能用於載入的圖片,如果圖片尺寸不是正方形,則會按照長寬中較小的值進行裁剪,以確保最終裁剪後的形狀為圓形。 - 由於 circleCrop() 方法需要對圖片進行裁剪操作,可能會增加一些計算和渲染的開銷,因此要謹慎使用,避免影響效能。 ::: ### **◆ centerCrop()**:方法用於將圖像裁剪為正方形,並將其居中顯示在 ImageView 中。 :::success - :::spoiler ※===centerCrop()介紹===※ - ![image](https://hackmd.io/_uploads/BkDbBM0xR.png) - 它會先將圖像縮放到最大尺寸以使其完全適合正方形,然後將其裁剪為正方形並居中顯示。 - 如果載入的圖片尺寸與目標視圖尺寸不匹配,則會根據寬高比例裁剪圖片以填滿目標視圖,因此可能會裁剪掉圖片的部分內容。 - 如果要保留圖片的全部內容並且不裁剪圖片,可以考慮使用 fitCenter() 方法,它會在填充目標視圖的同時保持圖片的完整內容可見,但可能會留有空白區域。 ::: ### **◆ fitCenter()**: 將圖像縮放到最大尺寸以使其完全適合 ImageView,同時保持圖像的縱橫比。 :::info - :::spoiler ※===fitCenter()介紹===※ - 如果圖像的縱橫比與 ImageView 的縱橫比不同,則圖像可能會留有黑邊。 - 如果載入的圖片尺寸與目標視圖尺寸不匹配,則會根據寬高比例進行等比例縮放,以確保圖片完整地顯示在目標視圖內。 - 與 centerCrop() 不同,fitCenter() 不會裁剪圖片或改變圖片的寬高比例,而是將整個圖片都顯示在目標視圖內,可能會留有空白區域。 ::: ### **◆ dontTransform()**: 用於載入圖片時禁用所有轉換,包括縮放、裁剪、旋轉等。 :::success - :::spoiler ※===dontTransform()介紹===※ - 使用`dontTransform()`意味著圖像將以其原始大小和縱橫比顯示在 ImageView 中。 - 在大多數情況下,不建議使用 `dontTransform()` 方法。這是因為 Glide 提供的默認轉換通常會優化圖像的顯示效果。 - 使用 dontTransform() 方法載入大尺寸圖片時可能會導致記憶體消耗增加,因為載入的是原始圖片而不是經過轉換後的圖片,所以需要權衡記憶體使用和載入速度。 ::: ### **◆ dontAnimate()**: 用於禁用圖像載入時動畫。 :::info - :::spoiler ※===dontAnimate()介紹===※ - 當使用此方法時,圖像將立即顯示在 ImageView 中,而不會出現淡入或淡出效果。 - `dontAnimate()` 方法僅適用於「圖像載入時的動畫特效(進出場特效)」。並不會禁用本來就是動畫的圖象,例如 GIF 動畫。 - 在低端設備上,動畫可能會導致性能下降。如果您需要在低端設備上提高性能,可以使用 `dontAnimate()` 方法來禁用動畫。 ::: ### **◆ placeholder()**: 用於指定在圖像載入之前或期間要顯示的圖片。 :::success - :::spoiler ※===dontAnimate()介紹===※ - 當圖像載入完成後,佔位圖片將被替換為實際圖像 - `placeholder()`裡面需填入Drawable物件或資源位址當作參數![image](https://hackmd.io/_uploads/SyIfAGRx0.png) - 佔位圖應該是輕量級的,以確保在網路請求未完成或載入延遲時,能夠快速顯示在介面上,提供良好的使用者體驗。 - 如果需要在載入失敗時顯示不同的佔位圖,可以考慮使用 error() 方法來設定載入失敗時的佔位圖。 - ![image](https://hackmd.io/_uploads/Hy7_kXAlR.png) ::: ### **◆ addListener()**: Glide 中的 `addListener()` 方法用於在圖像載入過程中監控事件並執行自訂操作。它允許您在圖像載入開始、完成、失敗或進度更新時執行程式碼。 :::info - :::spoiler ※===addListener()介紹===※ addListener()提供了數種方法可供覆寫: - **`onResourceReady()`:** 在圖像載入完成並成功顯示在 ImageView 中時調用。 - **`onLoadFailed()`:** 在圖像載入失敗時調用。 - **`onStarted()`:** 在圖像載入開始時調用。 - **`onProgress()`:** 在圖像載入進度更新時調用。 - 備註:`onResourceReady()`和`onLoadFailed()`是必須被複寫的。 ``` Glide.with(context) .load(url) .addListener(object : RequestListener<Drawable>() { override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean) : Boolean { // 在圖像載入完成時執行此程式碼 return false } override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?) : Boolean { // 在圖像載入失敗時執行此程式碼 return false } override fun onStarted(placeholder: Drawable?) : Boolean { // 在圖像載入開始時執行此程式碼 return false } override fun onProgress(percentage: Int, loaded: Long, total: Long) : Boolean { // 在圖像載入進度更新時執行此程式碼 return false } }) .into(imageView) ``` ::: ▼※一些其他的設定(2)※ --- ==**這些設定,必須寫在`load()`之前,不然無法使用。**== ### **◆ asGif()**: 將圖像加載為`GifDrawable` 物件。 :::success - :::spoiler ※===asGif()介紹===※ - ![1713405545263](https://hackmd.io/_uploads/H1E5Re0xR.gif) - 如果加載的圖片本來就是Gif動圖,那就算不使用`asGif()`,圖片還是會動,相反的,如果要讓Gif動圖不動,就得使用其他的`as`系列(例如: `asBitmap()`或`asDrawable()`) - ==`asGif()`最重要的效果是將非Gif圖片加載為GifDrawable物件==(這樣才能做其他Gif相關操作) ::: ### **◆ asFile()**: 將圖像加載為 `File` 物件。通常用於將圖像保存到本地存儲或用於其他目的。 :::info - :::spoiler ※===asFile()介紹===※ - `asFile()`方法是**異步**的,这意味着它將在子執行緒中執行。如果您需要在主執行緒中處理已下載的圖像文件,則需要使用 `submit()` 方法來提交請求並在回調函式中處理結果。 - `asFile()`方法只能加載靜態圖像,不能加載 GIF 動畫。 ::: ### **◆ asDrawable()**: 將圖像加載為Drawable物件。 :::success - :::spoiler ※===何謂Drawable物件===※ - Drawable(可繪製物件): - 定義:Drawable 是 Android 平台上可繪製圖形的基本類別。 它可以是點陣圖、形狀、圖層列表、向量圖等各種形式。 - 特點:Drawable 可以是靜態的或動態的,可以用來繪製在 View 上、作為背景、作為圖示等等。 - 常見類型:包括 BitmapDrawable(點陣圖可繪製物件)、ShapeDrawable(形狀可繪製物件)、LayerDrawable(圖層清單可繪製物件)、VectorDrawable(向量圖可繪製物件)等。 - 用法:通常透過資源檔案(如 XML、圖片檔案等)或程式碼動態建立 Drawable 對象,並將其應用於 View 或其他 UI 元素。 ::: ### **◆ asBitmap()**: 將圖像加載為 Bitmap。 :::info - :::spoiler ※===何謂Bitmap物件===※ - Bitmap(點陣圖物件): - 定義:Bitmap 是 Android 平台上表示影像的點陣圖類別。 它用於表示圖像的像素數據,可以是從文件、資源、網路等來源載入的圖像。 - 特點:Bitmap 是一個二維像素數組,包含了影像的像素訊息,可以對其進行像素級的操作和處理。 - 用途:Bitmap 可用於顯示在 ImageView、繪製在 Canvas 上、儲存到檔案、傳送到網路等操作。 - 建立方式:可以從檔案、資源、網路加載,也可以透過程式碼建立空白的 Bitmap,並在其中繪製圖形。 - 參考: [Android筆記(kotlin)–onDraw()、畫簡單幾何圖形、放置圖片(可縮放)、BitmapFactory](https://hackmd.io/@9YAtszqXS2OLNZOrLY_-Jg/android_onDraw_BitmapFactory) ::: --- ※踩坑紀錄1※ : Glide圖片變換功能 --- - [Android图片加载框架最全解析(五),Glide强大的图片变换功能](https://blog.csdn.net/guolin_blog/article/details/71524668) 簡述:在RecyclerView中使用了GLide,並使用.override()來試圖調整圖片大小,結果圖片本身沒有變,變的反而是圖片的解析度????? --- ※踩坑紀錄2※: 關於error()的各種限制 --- #### - 問題1.我想在error()中加入兩個功能(例如說同時顯示Toast跟錯誤圖片),結果失敗了,預設一次只能一種功能(),雖然可以用改變程式碼順序來繞過這問題,不過不太穩定,使用`addListener()`或許可以? ==※解決方法、原因※== : (尚未有結論) --- #### - 問題2.我想在error()中加載Gif動圖,結果失敗了,即使是使用 ``` error(Glide.with(itemView.context).asGif().load(Gif圖源).into(imageView_1_rowFunction)) 或是 error(Glide.with(itemView.context).asGif().load(Gif圖源)) ``` 這種方式來試圖確保加載的圖片是Gif也無效。 :::success :::spoiler ※===解決方法、原因===※: 在load()前面多加上asGif(),並將error()改成: ``` error(Glide.with(itemView.context).asGif().load(R.drawable.pusheen_pusheen_cat)) ``` 即可,推測可能是某種類似於型別轉換的問題所造成的(非GifDrawable物件不能用GifDrawable去替換) 解法1: ![image](https://hackmd.io/_uploads/HkzO4Z0xR.png) 解法2: 經實驗後發現,直接使用`asDrawable()`加載為Drawable物件也可以達到一樣的效果。 而且此方法可以不用在`error()`中加寫`asGif()` ![image](https://hackmd.io/_uploads/HytUY-AgC.png) ::: --- 參考資料: --- - [\[Android Studio 30天挑戰\] Day21 - 介紹Glide](https://ithelp.ithome.com.tw/articles/10302638?sc=iThelpR) - [[Android 開發經驗三十天\]#D26一Glide教學+小畫家繼續](https://ithelp.ithome.com.tw/articles/10251247) :::spoiler Android图片加载框架最全解析 系列 ==警告:這系列是2017年的舊文章,可能會有未知的錯誤,但是因為極具參考價值所以還是放進筆記裡了== - [Android图片加载框架最全解析(一)--Glide的基本用法](https://blog.csdn.net/guolin_blog/article/details/53759439) - [Android图片加载框架最全解析(二),从源码的角度理解Glide的执行流程](https://blog.csdn.net/guolin_blog/article/details/53939176) - [Android图片加载框架最全解析(三),深入探究Glide的缓存机制](https://blog.csdn.net/guolin_blog/article/details/54895665) - [Android图片加载框架最全解析(四),玩转Glide的回调与监听](https://blog.csdn.net/guolin_blog/article/details/70215985) - [Android图片加载框架最全解析(五),Glide强大的图片变换功能](https://blog.csdn.net/guolin_blog/article/details/71524668) - [Android图片加载框架最全解析(六),探究Glide的自定义模块功能](https://blog.csdn.net/guolin_blog/article/details/78179422) - [Android图片加载框架最全解析(七),实现带进度的Glide图片加载功能](https://blog.csdn.net/guolin_blog/article/details/7835725) - [Android图片加载框架最全解析(八),带你全面了解Glide 4的用法](https://blog.csdn.net/guolin_blog/article/details/78582548) :::