Android 開發中需要處理圖片的地方很多,但如何針對 Android 平臺的特性,將圖片這件不簡單的事情,做到順滑流暢則沒那么簡單。今天就分析下,Google 推薦的 Glide 開源框架,看看這個框架如何做好這件不簡單的事情。
Glide 為什么優秀?
首先來分析下,一個優秀的圖片庫應該具有什么樣的特性?
- 易用性。這對于絕大多數開源庫而言,都是需要做到的,但這又是很難的一方面。舉個例子,圖片庫涉及到網絡、緩存、編碼等等各個環節,但這些環節不應該讓所有用戶都知曉,應該拿捏到這種力度:用戶可以不知曉,有需求的可以進行自定義。開源庫可能有很多類用戶可以涉及,但最好有統一的外觀(Facade Pattern),Glide 在這點上就做得足夠好。
- 擴展性。需求這東西嘛,總是比天氣變化快多了,設計的開源庫就必須得有很好的擴展性。無論是 Volley,Glide 還是其他知名開源庫,在這點上都做得很好。關鍵在于抽象::不變的與變化的::,變化的是
網絡
,編碼
和緩存
等等模塊,不變的是它們之間是如何銜接的。在合理的抽象建模下,還是很容易高的擴展性的。 - 高性能與低占用。這是圖片庫最核心的部分,也是最難的部分。難點在于三個方面。
- 內存受限。受限于移動終端的低內存,如果占用內存過大,會使得分配變得低效,不穩定。如果復用不給力,高頻率的分配內存,會導致GC頻繁,從而卡頓。
- 流暢性。Android 系統中的圖片常用于 RecyclerView,GridView 中,這些控件往往展示著大量的圖片,在這些圖片頻繁加載、編碼等等情況下,保證滑動流暢呢?
- 生命周期。Android的UI組件有各個周期,Glide 要在盡可能少入侵代碼的前提下,參與到生命周期里面去,從而合理地分配和釋放資源。
Glide 如何做到易用性的?
本節和后序的章節,暫不涉及具體的源碼,后續的文章再做分析。要想要讓 Glide 易用,主要還是在 API 的設計上面。這里提出一個概念,鏈式調用
,是指一些方法能夠直接通過.
的形式進行連接。
Glide.with(this).load(url).placeholder(resId).error(resId).into(mImageView);
上面的代碼就是一個鏈式調用的例子,將 Glide 需要配置的地方,用一行代碼就可以表達出來。我們常見的 RxJava、Java Builder 等等都采用了這種方式。
除了鏈式調用以外,Glide 的易用性,還提現在完善的職能模塊,簡單明了的接口。用戶可以根據自身的需要進行自定義,也可以使用默認的方案。
Glide API
如上圖所示,Glide 將用戶能夠自定義的內容,都通過模塊和相應的接口暴露出來,開發者可以根據自身需要,只對部分模塊進行自定義即可。
Glide 如何實現高的擴展性?
高的擴展性前提就是清晰的模塊劃分,只有在這種情況下,模塊才能進行插拔
和替換
,從而實現擴展性。
Glide Module
Glide 在大體上劃分為Request
、Cache
、Module
、Decode
等等模塊,統一由Registry
進行管理。在這個基礎上,Glide 就能實現很好的擴展性。例如 Request
模塊,即可以使用默認的,也可以使用Volley
或者OKHttp
。
Glide 如何實現好的性能?
Glide 的性能方面的掌控,主要由三個方面來實施的。
- 良好的復用模塊。這是最核心的部分,當這塊內存能夠不斷地被循環使用,能減少 GC 和分配的次數。內存操作一般情況下,都是 Stop the world 的,UI 線程也會因此中斷,因而這對 APP 的性能極為關鍵。復用手段包括,但不止
LruCache
、Object Pool
。 - 本地化的生命周期。對于圖片資源的釋放,很少在保證即時性的情況下,又不需要開發者感知的。Glide 通過一個小技巧達成了目的,后續文章具體介紹哈。
- 對 RecyclerView 等等控件的細節調優。不要小看這些細節,羅馬就是這么搭建出來的,摳的這些小細節,才是大師所為。
文檔信息
- 版權聲明:自由轉載-非商用-非衍生-保持署名(創意共享3.0許可證)
- 發表日期:2017年10月22日
- 社交媒體:weibo.com/woaitqs
- Feed訂閱:www.woaitqs.cc/feed.xml