化實(shí)踐指南)
先說明一點(diǎn)在絕大多數(shù) Android 項(xiàng)目里圖片加載卡頓和 OOM 并不是 Glide 這個庫不行而是我們常常只把它當(dāng)成“一行代碼顯示圖片”的工具沒有真正理解它每一層配置背后的意義。Glide 如今幾乎是 Android 生態(tài)里的標(biāo)配圖片加載方案它把 Bitmap 解析、緩存、生命周期綁定、加載優(yōu)先級、圖片變換這些能力都集中到了一套 API 里。這篇稿子不打算逐行分析源碼而是從“圖片加載為什么會慢”“Glide 原理上到底做了什么”“日常編碼該怎么配置”“線上問題怎么排查”這條完整鏈路展開適合剛接手圖片模塊的開發(fā)者也適合團(tuán)隊(duì)做性能優(yōu)化復(fù)盤時對照使用。1. 圖片加載為什么會成為應(yīng)用性能的短板1.1 從點(diǎn)擊一張圖到屏幕顯示中間到底發(fā)生了什么用戶看到一張圖片背后并不是“文件下載完直接顯示”這么簡單。一次完整的圖片加載大概要經(jīng)過這樣幾步網(wǎng)絡(luò)下載或緩存讀取、輸入流解析、圖片寬高讀取、根據(jù)目標(biāo)尺寸計(jì)算采樣率、解碼產(chǎn)出 Bitmap、按 ImageView 尺寸做裁剪或縮放、最后上傳 GPU 或交由 Canvas 繪制。這中間任何一個環(huán)節(jié)失控都可能讓界面掉幀。最容易誤導(dǎo)人的一點(diǎn)是Bitmap 占用的內(nèi)存等于寬乘高乘每像素字節(jié)數(shù)和文件大小不是一回事。一張 1080×1920 的圖使用 ARGB_8888 格式解碼內(nèi)存占用大約是 1080×1920×4 字節(jié)約 8MB。服務(wù)端返回的 JPEG 文件可能只有幾百 KB一到客戶端解碼就變成幾 MB 甚至幾十 MB。如果列表一屏有十來個頭像每個都按原圖規(guī)格去解碼內(nèi)存和 GC 壓力會非常明顯。圖片優(yōu)化本質(zhì)上就是對這個鏈路做“按需供給”只加載你需要的尺寸只解碼你需要的精度只緩存你應(yīng)該復(fù)用的內(nèi)容。而不是籠統(tǒng)地“把圖片變小一點(diǎn)”。1.2 不做優(yōu)化會產(chǎn)生哪些直接后果我見過不少項(xiàng)目把網(wǎng)絡(luò)圖片加載寫成“開線程下載流然后 BitmapFactory.decodeFile最后 runOnUiThread setImageBitmap”。這種寫法在小 Demo 里沒問題一到線上什么問題都會冒出來圖片解碼放在子線程但沒有做采樣超大圖被完整解碼到內(nèi)存OOM 只差時間?;卣{(diào)回來直接操作 View完全不判斷頁面是否還在Activity 銷毀后依然更新 UI。沒有任何緩存同一張圖反復(fù)請求流量和耗時都被白白浪費(fèi)。頻繁創(chuàng)建 BitmapGC 不斷觸發(fā)RecyclerView 滑動時幀率極不穩(wěn)定。圖片 URL 不變但內(nèi)容變了客戶端永遠(yuǎn)顯示舊圖只能清應(yīng)用數(shù)據(jù)。這些問題不是靠一兩個工具類能解決的它需要一套完整的圖片加載體系。Glide 的存在價值就是把這些通用問題收斂到一個統(tǒng)一框架里處理。我們使用它不等于把全部問題甩給框架還得搞清楚它內(nèi)部替你做了什么、沒做什么。2. Glide 核心原理拆解為什么它能做到又快又穩(wěn)2.1 生命周期綁定請求隨頁面一起暫停和取消Glide 的 with 方法接受 Activity、Fragment、View 或 Context。傳入 Activity 或 Fragment 時它會在當(dāng)前頁面掛一個無 UI 的 Fragment用來監(jiān)聽生命周期回調(diào)。宿主的 onStart 時恢復(fù)請求onStop 時暫停請求onDestroy 時取消請求并釋放資源。這個機(jī)制的意義非常明顯。圖片加載是異步的如果頁面已經(jīng)退出網(wǎng)絡(luò)請求還在發(fā)ImageLoading 回調(diào)還試圖更新 View輕則白費(fèi)帶寬重則內(nèi)存泄漏或崩潰。Glide 把“請求是否應(yīng)該繼續(xù)”和頁面生命周期綁定在一起是它能穩(wěn)定運(yùn)行在大量列表場景的基礎(chǔ)。但要特別注意如果 with 傳入 ApplicationContext就失去了頁面生命周期綁定能力。請求不會隨頁面銷毀而取消。這種寫法適合真正全局性的加載場景比如通知欄圖片、桌面小組件之類。普通頁面加載圖片都應(yīng)該優(yōu)先傳 Activity 或 Fragment。2.2 三級緩存與請求去重省的不只是流量Glide 的緩存體系可以粗略分成三層活動資源、內(nèi)存緩存、磁盤緩存?;顒淤Y源是正在被使用的 Bitmap內(nèi)存緩存基于 LruCache 實(shí)現(xiàn)按最少使用策略淘汰磁盤緩存負(fù)責(zé)把處理后的圖片或原始數(shù)據(jù)持久化到本地。有一個關(guān)鍵點(diǎn)是緩存 key 的生成。同一個 URL 不一定命中同一條緩存因?yàn)?key 會結(jié)合目標(biāo)寬高、圖片變換、簽名、緩存策略等因素。同一張圖一個場景按 200×200 centerCrop 加載另一個場景按 800×800 fitCenter 加載兩個請求的緩存 key 不一樣內(nèi)存里會存在兩張 Bitmap。這在邏輯上是正確的但如果業(yè)務(wù)上沒做統(tǒng)一很容易出現(xiàn)同圖多尺寸重復(fù)緩存白白占用磁盤空間。請求去重則是列表場景的福音。RecyclerView 快速滑動時如果多個 item 加載同一張頭像Glide 會把相同 key 的請求合并只發(fā)一次網(wǎng)絡(luò)請求等結(jié)果返回后同時分發(fā)給所有目標(biāo)。這能極大減少重復(fù)請求和重復(fù)解碼比手動做內(nèi)存緩存要可靠得多。2.3 采樣解碼和 Bitmap 復(fù)用內(nèi)存優(yōu)化的真正功臣Glide 并不是把整張?jiān)瓐D解碼出來再按比例縮小而是在解碼階段就參考 ImageView 尺寸計(jì)算采樣率使用 inSampleSize 讀取部分像素。也就是說加載一個 200×200 的頭像時它不會把服務(wù)端 1080×1920 的圖完整解出來再縮小而是直接按采樣率跳過一部分像素解碼結(jié)果本身就更小。這種“先壓縮再解碼”的方案能顯著降低內(nèi)存峰值。同時Glide 內(nèi)部維護(hù)了一個 BitmapPool。當(dāng)一個 Bitmap 不再被引用時它的內(nèi)存不會立刻還給系統(tǒng)而是放進(jìn)池子里等待復(fù)用。這樣后面加載新圖時可以直接使用舊內(nèi)存塊減少系統(tǒng)分配和 GC 次數(shù)。我給團(tuán)隊(duì)做優(yōu)化時經(jīng)常強(qiáng)調(diào)一點(diǎn)自定義 Transformation 時不要自己 new Bitmap。如果你在 transform 方法里手動創(chuàng)建新圖等于繞過了 BitmapPool內(nèi)存和穩(wěn)定性都會變差。要盡量通過 Glide 提供的接口申請復(fù)用內(nèi)存或者明確釋放不復(fù)用的對象。2.4 線程模型與優(yōu)先級調(diào)度Glide 的網(wǎng)絡(luò)請求和解碼任務(wù)都發(fā)生在后臺線程池主線程只保留最終 UI 更新和必要的生命周期回調(diào)。它還支持 IMMEDIATE、HIGH、NORMAL、LOW 四檔優(yōu)先級。列表滾動時當(dāng)前可見位置的圖片請求會被安排得更靠前用戶會感覺首屏加載更快。這里要澄清一個誤區(qū)priority 不是絕對搶占。它改變的是同一批等待任務(wù)里的調(diào)度順序不等于你先調(diào) IMMEDIATE 就能立刻無視其他任務(wù)。它更適合用來做視覺上的主次區(qū)分比如詳情頁第一張主圖給 HIGH下面普通配圖給 NORMAL而不是拿它當(dāng)天馬行空的同步工具。3. 日常編碼里最值得養(yǎng)成的 Glide 使用習(xí)慣3.1 with() 到底該傳誰真的重要嗎很多項(xiàng)目會寫一個全局圖片加載工具類內(nèi)部用一個靜態(tài) context 持有 ApplicationContext然后所有地方都走這個工具類。這種封裝好處是把 url 和配置統(tǒng)一起來壞處是 Glide 失去了頁面生命周期感知能力。我推薦的原則是在 Activity 里加載圖片用Glide.with(this)。在 Fragment 里加載圖片用Glide.with(this)或getContext()。在 RecyclerView Adapter 里優(yōu)先使用holder.itemView.getContext()。ApplicationContext 只留給確確實(shí)實(shí)不關(guān)心頁面是否銷毀的加載任務(wù)。還要注意一個很實(shí)際的坑Glide.with() 要求在 Android 主線程調(diào)用。有人會在協(xié)程 IO 線程里先處理 URL然后直接在 IO 線程執(zhí)行 Glide.with多半會在運(yùn)行期拋異常。遇到這個問題先把調(diào)用切回主線程或者把加載動作放到 UI 層統(tǒng)一調(diào)度。3.2 占位圖、錯誤圖、fallback 和過渡動畫別混成一鍋placeholder 是加載中顯示的圖error 是加載失敗顯示的圖fallback 是 URL 為空時顯示的圖。三者語義完全不同。很多業(yè)務(wù) URL 可能為空如果只設(shè)置了 error沒有 fallback圖片為空時會被當(dāng)成失敗處理界面會展示錯誤占位觀感很差。設(shè)置方式很簡單Glide.with(imageView.getContext()) .load(imageUrl) // imageUrl 可能為 null .placeholder(R.drawable.ic_placeholder) .error(R.drawable.ic_error) .fallback(R.drawable.ic_fallback) .into(imageView);過渡動畫方面我建議謹(jǐn)慎使用 crossFade。淡入效果確實(shí)能增加細(xì)膩感但列表快速滑動時如果圖片從內(nèi)存緩存命中交叉淡入會造成視覺閃動也容易掉幀。頭像列表、信息流列表我一般不默認(rèn)加 crossFade只在詳情大圖場景單獨(dú)使用。3.3 尺寸和裁剪方式是性能優(yōu)化里最立竿見影的一步我見過很多加載代碼只寫了 load 和 into沒有 override也沒有 centerCrop。如果 ImageView 沒有明確寬高Glide 只能按原始圖片尺寸去解碼或者等布局完成后再觸發(fā)一次加載。這會造成內(nèi)存浪費(fèi)也容易出現(xiàn)圖片忽大忽小。更合理的寫法是明確目標(biāo)尺寸并按展示需求選擇裁剪方式。centerCrop 會等比縮放并裁剪中間部分適合頭像和一屏鋪滿的照片fitCenter 會完整顯示整張圖片適合詳情頁長圖和需要看全貌的圖。Glide.with(context) .load(url) .override(400, 400) .centerCrop() .placeholder(R.drawable.ic_placeholder) .error(R.drawable.ic_error) .into(imageView);如果列表里每個 item 尺寸固定盡量把 RequestOptions 抽成靜態(tài)常量不要在 bind 方法里反復(fù) new 對象。頻繁創(chuàng)建請求配置雖然單個對象很小但疊加到列表成千上萬次綁定上依然是完全可以避免的開銷。3.4 磁盤緩存策略不是越大越好Glide 4.x 的 DiskCacheStrategy 有 NONE、DATA、RESOURCE、ALL、AUTOMATIC 幾種選擇。DATA 只緩存原始網(wǎng)絡(luò)數(shù)據(jù)每次顯示圖片時都需要重新解碼RESOURCE 緩存處理后的圖片下次加載快但緩存的是按 View 尺寸處理過的版本不同尺寸會形成不同緩存ALL 則兩者都緩存速度和空間消耗都最高AUTOMATIC 會基于圖片資源類型做默認(rèn)選擇。實(shí)際場景我一般這樣選頭像、商品圖、播放頁封面這類高度復(fù)用的圖片用 AUTOMATIC 或 ALL驗(yàn)證碼、實(shí)時行情圖、一次性活動圖用 NONE避免緩存堆積。還有就是圖片內(nèi)容會定期變化的 URL不能只依賴緩存策略一定要給請求加簽名比如把圖片更新時間拼進(jìn) signature讓緩存 key 發(fā)生變化。常見坑是服務(wù)端更新了圖片但 URL 沒變客戶端一直顯示舊圖。很多人第一反應(yīng)是清應(yīng)用緩存但正確做法是用簽名或文件名版本號來主動失效舊緩存。3.5 縮略圖和加載優(yōu)先級讓用戶心理上覺得“更快”如果加載詳情頁大圖我強(qiáng)烈建議用 thumbnail。thumbnail 不是普通占位圖它是在同一個 URL 基礎(chǔ)上按百分比再加載一個縮小版圖片先顯示小圖原圖加載完成后自動替換。這樣用戶進(jìn)入頁面時很快能看到畫面輪廓體感加載速度會好很多。Glide.with(context) .load(url) .thumbnail(0.1f) .into(imageView);同一頁面多張圖片時可以用 priority 調(diào)整加載順序。比如詳情頁第一屏主圖設(shè) HIGH下方推薦位圖片設(shè) NORMAL這樣網(wǎng)絡(luò)和解碼資源會優(yōu)先給最可能先被看到的圖。但再次強(qiáng)調(diào)priority 不是絕對的同步鎖不能依賴它保證加載完成順序。4. 把 Glide 接入項(xiàng)目后的擴(kuò)展與監(jiān)控4.1 AppGlideModule 是全局配置的唯一入口如果項(xiàng)目需要對 Glide 做全局性調(diào)整比如修改磁盤緩存大小、默認(rèn)解碼格式、日志級別可以寫一個 AppGlideModule。4.x 版本里編譯期注解處理器會自動生成注冊代碼不需要在 Manifest 里手動聲明。一個簡單示例GlideModule public class MediaGlideModule extends AppGlideModule { Override public void applyOptions(Context context, GlideBuilder builder) { builder.setDefaultRequestOptions( new RequestOptions().format(DecodeFormat.PREFER_RGB_565)); builder.setDiskCache( new DiskLruCacheFactory(context.getCacheDir(), image_glide_cache, 200 * 1024 * 1024)); } }這里有個實(shí)際教訓(xùn)全局只能有一個 AppGlideModule。如果依賴的第三方庫內(nèi)部也注冊了 AppGlideModule編譯期會直接提示沖突。遇到這種問題需要找依賴庫的源碼或配置把它排除掉而不是硬寫兩個。默認(rèn)解碼格式 ARGB_8888 對圖片質(zhì)量最友好但內(nèi)存占用也最高。RGB_565 沒有 alpha 通道能省一半內(nèi)存適合縮略圖、一般照片和不帶透明度的圖片。如果圖片里有細(xì)膩漸變色RGB_565 可能出現(xiàn)色帶所以要按業(yè)務(wù)場景權(quán)衡不要全局無腦切。4.2 替換網(wǎng)絡(luò)請求層讓圖片請求融入項(xiàng)目統(tǒng)一體系Glide 默認(rèn)使用 HttpURLConnection 拉取網(wǎng)絡(luò)圖片。但大部分項(xiàng)目的網(wǎng)絡(luò)層都基于 OkHttp里面有 token、統(tǒng)一 Header、日志上報(bào)、DNS 等邏輯。如果圖片網(wǎng)絡(luò)請求不走這套體系會帶來兩個問題一是無法復(fù)用連接池二是無法統(tǒng)一攔截和監(jiān)控。我們可以注冊一個 LibraryGlideModule把 Glide 默認(rèn)的 HttpUrlLoader 替換成基于 OkHttp 的實(shí)現(xiàn)。替換之后圖片請求會自動繼承 OkHttp 的連接池、超時配置和攔截器對整體網(wǎng)絡(luò)調(diào)優(yōu)非常有幫助。這種做法并不復(fù)雜但要注意替換方式。LibraryGlideModule 適合庫項(xiàng)目使用應(yīng)用項(xiàng)目也可以注冊。替換完以后最好先做一次線上回歸重點(diǎn)檢查 HTTPS 圖片、重定向 URL、斷點(diǎn)續(xù)傳和攔截器是否兼容。圖片在弱網(wǎng)環(huán)境的表現(xiàn)通常會比默認(rèn) HttpURLConnection 更好。4.3 通過 RequestListener 監(jiān)控圖片加載質(zhì)量圖片優(yōu)化不能只憑感覺。我習(xí)慣在關(guān)鍵圖片請求上掛一個 RequestListener統(tǒng)計(jì) onResourceReady 時圖片來源和耗時。命中內(nèi)存緩存非??烀写疟P緩存較快網(wǎng)絡(luò)加載最慢。把這幾類數(shù)據(jù)分開統(tǒng)計(jì)能很快定位慢圖到底慢在哪個環(huán)節(jié)。Glide.with(context) .load(url) .listener(new RequestListenerDrawable() { Override public boolean onLoadFailed(Nullable GlideException e, Object model, TargetDrawable target, boolean isFirstResource) { // 上報(bào)失敗原因 return false; } Override public boolean onResourceReady(Drawable resource, Object model, TargetDrawable target, DataSource dataSource, boolean isFirstResource) { // 記錄 dataSource 和耗時 return false; } }) .into(imageView);這里特別要提醒listener 返回 true 表示你已經(jīng)消費(fèi)了這個事件Glide 會中斷后續(xù)邏輯。如果只是想觀察數(shù)據(jù)必須返回 false。不少人不小心返回 true導(dǎo)致圖片不顯示排查了很久才發(fā)現(xiàn)是監(jiān)聽器把流程攔斷了。4.4 列表頁的專項(xiàng)優(yōu)化清單RecyclerView 是圖片性能問題最集中的地方。一些穩(wěn)定高效的細(xì)節(jié)我列在下面不要在每個 bind 方法里重新創(chuàng)建 RequestOptions抽成靜態(tài)常量復(fù)用。不要在自定義 View 的 onDraw 或 layout 回調(diào)里觸發(fā) Glide 加載調(diào)用頻率過高會產(chǎn)生大量無效請求。固定尺寸的列表圖用 centerCrop override避免解碼出多余像素。item 復(fù)用時普通場景默認(rèn)用 into(ImageView)它會自動取消上一個請求避免新舊圖錯亂。如果同一張圖在不同位置需要不同尺寸盡量讓服務(wù)端按場景返回對應(yīng)規(guī)格而不是客戶端反復(fù)做變換。列表滾動時如果發(fā)現(xiàn)明顯掉幀先不要急著優(yōu)化算法可以打開 Android Studio 的 Profile 看看內(nèi)存和 GC。大量 GC 停頓往往就是 Bitmap 頻繁創(chuàng)建導(dǎo)致的先用 Glide 把尺寸和緩存收斂好再追求更復(fù)雜的性能技巧。5. 線上常見問題與排查技巧實(shí)錄5.1 圖片一直占位但不報(bào)錯可能卡在哪兒遇到圖片一直顯示占位圖第一條檢查 URL 是否可訪問。Android 9 以后默認(rèn)禁止明文 HTTP 請求如果地址是 http 而配置沒放開Glide 請求會直接失敗表現(xiàn)就是占位圖一直掛著頁面也不一定崩潰。處理方式是按項(xiàng)目規(guī)范配置網(wǎng)絡(luò)安全策略或者把資源切到 HTTPS。第二個常見點(diǎn)是磁盤緩存異常。舊緩存文件損壞時Glide 解碼會失敗。排查時可以臨時把 diskCacheStrategy 改成 NONE如果圖片恢復(fù)正?;究梢源_認(rèn)是緩存問題。線上不適合讓用戶手動清緩存可以考慮在版本升級后對緩存目錄做一次處理或清理。還有一個隱蔽原因RequestListener 的 onLoadFailed 返回 true。如果排查代碼時發(fā)現(xiàn)有監(jiān)聽器先把它改成返回 false再看圖片是否恢復(fù)。這個坑我踩過不止一次低級但真實(shí)。5.2 大圖 OOM 的排查與處理路徑OOM 不一定發(fā)生在網(wǎng)絡(luò)圖加載本地大圖、長截圖、相冊原圖也一樣。排查時先確認(rèn)三點(diǎn)ImageView 有沒有固定寬高、Glide 請求有沒有 override、圖片源是不是遠(yuǎn)大于顯示區(qū)域。常規(guī)降內(nèi)存路徑是給加載請求設(shè)置 override限制解碼尺寸不超過屏幕寬高。非透明圖使用 RGB_565 格式能省一半左右內(nèi)存。磁盤緩存策略優(yōu)先用 RESOURCE避免每次加載都重新解碼原始大圖。詳情大圖可以配合 thumbnail 先用小圖撐住視覺。BitmapPool 不是根治 OOM 的萬能藥它只是復(fù)用內(nèi)存真正問題往往是該縮放的沒縮放。如果服務(wù)端返回的圖動不動就是 6000×4000客戶端做得再好也有限。更合理的方案是服務(wù)端按場景輸出不同規(guī)格客戶端加載對應(yīng)的圖片地址。客戶端和服務(wù)端一起調(diào)優(yōu)效果遠(yuǎn)遠(yuǎn)好過單端硬扛。5.3 頁面銷毀后回調(diào)仍然執(zhí)行Glide 綁定生命周期后頁面銷毀時會取消請求。如果你發(fā)現(xiàn) onResourceReady 依然被回調(diào)多半是 with 里傳了 ApplicationContext或者請求是在單例、后臺工具類里發(fā)起的。這時 Glide 根本沒有宿主的生命周期可取自然也不會取消。另一個情況是自定義 Target。Glide 對普通 ImageView 能通過內(nèi)部機(jī)制管理請求但對自定義 Target 只能保證它自己不主動取消無法感知 View 是否存在。所以做后臺下載圖片再更新業(yè)務(wù)狀態(tài)的場景要自己判斷發(fā)起者是否仍然有效不能把狀態(tài)判斷完全交給 Glide。5.4 列表復(fù)用導(dǎo)致圖片錯亂或舊圖閃現(xiàn)RecyclerView 高速滾動時item 會被復(fù)用給新的位置。如果上一個位置的圖片請求還沒完成新的請求已經(jīng)發(fā)出返回順序可能和綁定順序不一致于是用戶會看到舊圖一閃或者最終顯示錯誤圖。Glide 的 into(ImageView) 本身會給 ImageView 綁定請求 key并在新加載時取消舊請求所以大多數(shù)場景不會錯圖。但如果是手動寫的 Target或者加載速度太快、占位圖是透明的舊圖殘留就會在替換前被看到。有效處理方式是給列表加載統(tǒng)一設(shè)置不透明的占位圖保證舊圖被遮蓋。更嚴(yán)格一點(diǎn)可以在 bind 前先給 ImageView 設(shè)置空背景或 tag再發(fā)起新的加載。大多數(shù)項(xiàng)目用默認(rèn) into 已經(jīng)足夠不需要強(qiáng)行自定義。5.5 常見問題速查表癥狀可能原因排查建議圖片一直顯示占位圖URL 不可達(dá)、HTTP 明文限制、磁盤緩存損壞、listener 吞事件檢查 URL 和網(wǎng)絡(luò)安全配置臨時關(guān)緩存檢查 RequestListener 返回值大圖加載 OOM沒有 override、目標(biāo)尺寸過大、原圖超大、App 內(nèi)存水位高固定 ImageView 尺寸overrideRGB_565配合服務(wù)端裁剪頁面銷毀后仍回調(diào)with 傳了 ApplicationContext、使用了自定義 Target改用頁面上下文在發(fā)起方增加有效性判斷圖片錯亂或舊圖閃現(xiàn)item 復(fù)用、加載順序不定、占位圖透明設(shè)置不透明占位使用默認(rèn) into必要時自定義 tag 校驗(yàn)更新了圖片但界面還是舊圖緩存 key 未變化、服務(wù)端未改 URL給請求加 signature讓 URL 帶版本參數(shù)圖片加載特別慢圖片過大、網(wǎng)絡(luò)層未復(fù)用連接池、服務(wù)端機(jī)器問題用 RequestListener 統(tǒng)計(jì)數(shù)據(jù)替換網(wǎng)絡(luò)層服務(wù)端按尺寸裁圖做圖片加載優(yōu)化這么久我個人的體會是Glide 學(xué)習(xí)成本不高真正難的是把它放進(jìn)整個業(yè)務(wù)體系里統(tǒng)一設(shè)計(jì)。每個頁面都獨(dú)立調(diào) Glide 參數(shù)短期看著靈活長期只會讓維護(hù)成本越來越高。最值得做的投入是在項(xiàng)目里做一層輕量封裝把 URL、尺寸、圓角、緩存策略、加載監(jiān)聽都收斂到統(tǒng)一入口這樣后續(xù)無論是調(diào)優(yōu)還是排查線上問題都有據(jù)可查。圖片加載不是一個點(diǎn)而是一條鏈路把生命周期、內(nèi)存、緩存和網(wǎng)絡(luò)這幾件事想明白了Glide 才能真正發(fā)揮出它應(yīng)有的價值。