上篇介紹了權限管理系列框架(http://blog.csdn.net/siwenyy/article/details/75093384 ),接下來圖片加載系列框架隆重登場了。
一、Glide(https://github.com/bumptech/glide)
是Google推薦的圖片加載和緩存框架,他完全是基於 Picasso 的,沿襲了 Picasso 的簡潔風格,但是在此做了大量優化與改進。
1.總體設計及流程
整個庫分爲RequestManager(請求管理器)、Engine(數據獲取引擎)、Fetcher(數據獲取器)、MemoryCache(內存緩存)、DiskLRUCache、Transformation(圖片處理)、Encoder(本地緩存存儲)、Registry(圖片類型及解析器配置)、Target(目標)等模塊
簡單來說,Glide收到加載及顯示圖片的任務,創建Request並將它交給RequestManager,Request啓動Engine去數據源獲取資源(通過Fetcher),獲取後由Transformation處理後交給Target
Glide依賴於DiskLRUCache、GifDecoder等開源庫去完成本地緩存和Gif圖片解碼工作
2.Glide優點
(1).圖片緩存-->媒體緩存
Glide不僅可以圖片緩存,它支持Gif、WebP、縮略圖,甚至是Video,所以更應該是一個媒體緩存
(2).支持優先級處理
(3).與Activity/Fragment生命週期一致,支持trimMemory:Glide對每個context都保持一個RequestManager,通過FragmentTransaction保持與Activity/Fragment生命週期一致,並且有對應的trimMemory接口實現可供調用
(4).支持okhttp、Volley
Glide默認通過HttpURLConnection獲取數據,可配合okhttp或Volley使用(ImageLoader、Picasso也都支持okhttp、Volley)
(5).內存友好
a.Glide的內存緩存有個active的設計
從內存緩存中獲取數據時,不像一般的實現用get,而是用remove,再將這個緩存數據放到一個value爲軟引用的activeResources map中,並計數引用數,在圖片加載完成後進行判斷,如果引用計數爲空則回收掉
b.內存緩存更小圖片
Glide以url、view_width、view_height、屏幕的分辨率等作爲聯合主鍵(key),將處理後的圖片緩存在內存緩存中,而不是原始圖片以節省大小
c.與Activity/Fragment聲明週期一致,支持trimMemory
d.圖片默認使用RGB_565而不是ARGB_888。雖然清晰度差些,但是圖片更小,也可配置到ARGB_888
其他:Glide可通過signature或不適用本地緩存支持url過期
備註:Glide框架的使用請參考 Glide框架的基本使用
二、Picasso(https://github.com/square/picasso )
是Square公司開源的一個Android平臺上的圖片加載框架,簡單易用
Downloader
DownLoader就是下載用的工具類,在Picasso當中,如果OKHttp可以使用的話,就會默認使用OKHttp,如果無法使用的話,就會使用UrlConnectionDownloader(默認使用HttpURLConnection實現)。
Cache
默認實現爲LruCache,就是使用LinkedHashMap實現的一個Cache類,注意的一個地方就是,在其他的地方,我們一般默認的是限制的capacity,但是這個地方我們是限制的總共使用的內存空間。因此LruCache在實現的時候,其實簡單理解就是將LinkedHashMap封裝,然後基於LinkedHashMap的方法實現Cache的方法,在Cache的set()方法的時候,會不斷計算當前還可以使用的空間大小,要是超出範圍,則刪除之前保存的數據。
ExecutorService
默認的實現爲PicassoExecutorService,該類也比較簡單,其實就是ThreadPoolExecutor,在其功能的基礎上繼續封裝,在其中有一個比較細心的功能就是,Picasso通過PicassoExecutorService設置線程數量,來調整在2G/3G/4G/WiFi不同網絡情況下的不同表現。
RequestTransformer
ReqeustTransformer是一個接口,用來預處理Reqeust,可以用來將請求進行預先處理,比如改個域名啥的。
Stats
主要是一些統計信息,比如cache hit/miss,總共下載的文件大小,下載過的圖片數量,轉換的圖片數量等等。
Dispatcher
Picasso當中,分發任務的線程,這是我們以後要重點研究的一個類,先標記一下,這個Dispatcher主要做了以下的事情:
啓動了一個DispatcherThread線程初始化了一個用來處理消息的DispatcherHandler,注意,根據Dispatcher中默認配置,該Handler所有數據的處理是在DispatcherThread之上。初始化並註冊了一個網絡狀態廣播接收器。
1.總體設計及流程
整個庫分爲Dispatcher、RequestHandler、Downloader、PicassoDrawable等模塊,Dispatcher負責分發和處理Action,包括提交、暫停、繼續、取消、網絡狀態變化、重試等等。
簡單來說,Picasso收到加載及顯示圖片的任務,創建Request並將它交給Dispatcher,Dispatcher分發任務到具體RequestHandler,任務通過MemoryCache和Handler(數據獲取接口)獲取圖片,圖片獲取成功後通過PicassoDrawable顯示到Target中
注:上面的Data的File system部分,Picasso沒有自定義本地緩存的接口,默認使用http本地緩存,API9以上使用okhttp,以下使用HttpURLConnection,因此如果要自定義 本地緩存就要衝定義Downloader。
2、圖片加載流程:
1).初始化Picasso,實例化其唯一的對象。
2).根據傳入的Url、File、resource Id,構建ReqeustCreator對象
3).根據ReqeustCreator構建Request對象,同時根據Reqeust屬性,嘗試從Cache中訪問數據
4).Cache Hit,則通過回調,設置Target或者ImageView,完成該Reqeust
5).如果Cache Miss,那麼則構建相應的Action,並提交到DispatcherThread當中。
6).Dispatcher中的Handler接收到相應的Message,調用dispatcher.performSubmit(action)進行處理。
7).創建BitmapHunter對象,並提交到PicassoExecutorService線程池
8).再次檢查Memory Cache中已經有緩存,如果Hit,則讀取緩存中的Bitmap
9).如果Cache miss,則交給Action對應的ReqeustHandler進行處理,比如網絡請求,或者從File讀取圖片
10).返回結果之後,通知Dispatcher中的Handler處理結果。
11).DispatcherThread中將BitmapHunter的結果打包(batch),最快200ms打包一次。通知主線程HANDLER進行處理
12).主線程HANDLER接收打包的BitmapHunter,對最後的結果進行分發。
注意:Picasso框架沒有實現磁盤緩存,配合OkHttp進行實現。
3.Picasso優點
(1).自帶統計監控功能:支持圖片緩存使用的監控,包括緩存命中率、已使用內存大小、節省的流量等
(2).支持優先級處理:每次任務調度前會選擇優先級高的任務,比如App頁面中Banner的優先級高於Icon時就很使用
(3).支持延遲到圖片尺寸計算完成加載
(4).支持飛行模式、併發線程數根據網絡類型而變:手機切換到飛行模式或網絡類型變換時會自動調整線程池最大併發數,比如wifi最大併發爲4,4g爲3,3g爲2。這裏Picasso根據網絡類型來決定最大併發數,而不是CPU的核數
(5)."無"本地緩存:不是說沒有本地緩存,而是Picasso自己沒有實現,交給了okhttp去實現,這樣的好處是可以通過請求Response Header中的Cache-Control及Expired控制圖片的過期時間
(6)Picasso實現了圖片的異步加載,並解決了Android中加載圖片時常見的一些問題,它有以下特點:
- 在Adapter中取消了不在視圖範圍內的ImageView的資源加載,因爲可能會產生圖片錯位
- 使用複雜的圖片轉換技術降低內存的使用
- 自帶內存和硬盤的二級緩存機制
歸納:
圖片加載失敗或出錯後顯示的圖片
圖片加載成功或失敗的回調
自定義圖片大小、自動測量ImageView大小、裁剪、旋轉圖片等
標籤管理,暫停和恢復圖片加載
請求優先級管理
可以從不同來源加載圖片,網絡、Resources、assets、files、content providers
更加豐富的擴展功能
三、Fresco (https://github.com/facebook/fresco )
是 Facebook 出品,他是新一代的圖片加載庫,我們知道 Android 應用程序可用的內存有限,經常會因爲圖片加載導致 OOM,所以Fresco他將圖片放到一個特別的內存區域叫 Ashmem 區,就是屬於 Native 堆,圖片將不再佔用 App 的內存,能大大的減少 OOM。
1.基本概念
(1)RequestManager:請求生成和管理模塊
(2)Engine:引擎部分,負責創建任務(獲取數據),並調度執行
(3)GetDataInterface:數據獲取接口,負責從各個數據源獲取數據,比如:從內存緩存獲取數據,從本地緩存獲取數據,下載器從網絡獲取數據等
(4)Displayer:資源(圖片)顯示器,用於顯示或操作資源
(5)Processor:資源(圖片)處理器,負責處理圖片,比如旋轉、壓縮、截取等
注:以上概念的稱呼在不同的框架中可能不同,如:Displayer在ImageLoader中叫ImageAware,在Picasoo和Glide中叫Target
2.Fresco優點
(1)兩個內存緩存和Native緩存構成了三級緩存
(2)支持流式,可以類似網頁上模糊漸進式顯示圖片
(3)十分強大,使用起來非常流暢,內存管理不用愁,不用擔心OOM
(4)圖片加載時可在佈局中直接設置加載動畫等等,代碼量大大減少
(5)支持多幀動畫圖片,如gif,WebP
- Fresco是一個強大的圖片加載組件
- Fresco中設計有一個叫做image pipeline 的模塊。他負責從網絡,從本地文件系統,本地資源加載圖片。爲了最大限度上節省空間和CPU時間,它含有3級緩存的設計(額,沒三級能拿出手?)
- Fresco中設計有一個叫做Drawees模塊,方便地顯示loading圖,當圖片不再顯示在屏幕上時,及時地釋放內存和空間佔用。
- Fresco支持Android2.3及以上系統
- 支持圖像漸進式呈現,大公司出品,後期維護有保障
3,必須全套使用fresco的圖片加載,否則連獲取簡簡單單的一個緩存中的bitmap都異常費勁
特點:有兩級內存一級文件的緩存機制,並且有自己特別的內存區域來處理緩存,避免oom
四、Universal-Image-Loader(https://github.com/nostra13/Android-Universal-Image-Loader )
MemoryCache圖片內存換成。默認使用了 LRU 算法。 LRU: Least Recently Used 近期最少使用算法, 選用了基於鏈表結構的 LinkedHashMap 作爲存儲結構。假設情景:內存緩存設置的閾值只夠存儲兩個 bitmap 對象,當 put 第三個 bitmap 對象時,將近期最少使用的 bitmap 對象移除。
DiskCache圖片磁盤緩存,默認使用LruDiskCache算法,在緩存滿時刪除最近最少使用的圖片;緩存目錄下名爲journal的文件記錄緩存的所有操作
1.總體設計及流程
整個庫分爲ImageLoaderEngine,Cache、ImageDownloader、ImageDecoder、BitmapDisplayer、BitmapProcessor五大模塊,其中,Cache分爲MemoryCache和DiskCache兩部分
簡單來說,ImageLoader收到加載及顯示圖片的任務,將任務交給ImageLoaderEngine,ImageLoaderEngine分發任務到具體線程池去執行,任務通過Cache及ImageDownloader獲取圖片,中間可能經過BitmapProcessor和ImageDecoder處理,最終轉換爲Bitmap交給BitmapDisplayer在ImageAware中顯示
2、圖片加載流程
1).判斷圖片的內存緩存是否存在,若存在直接執行步驟 8;
2).判斷圖片的磁盤緩存是否存在,若存在直接執行步驟 5;
3.ImageDownloader從網絡上下載圖片;
4.將圖片緩存在磁盤上;
5.ImageDecoder將圖片 decode 成 bitmap 對象;
6.BitmapProcessor根據DisplayImageOptions配置對圖片進行預處理(Pre-process Bitmap);
7.將 bitmap 對象緩存到內存中;
8.根據DisplayImageOptions配置對圖片進行後處理(Post-process Bitmap);
9.執行DisplayBitmapTask將圖片顯示在相應的控件上。
3.ImageLoader優點
(1).支持下載進度監聽
(2).可在View滾動中暫停圖片加載
通過PauseOnScrollListener接口可在View滾動中暫停圖片加載
(3).默認實現多種內存緩存算法:如Size最大先刪除、使用最少先刪除、最近最少使用、先進先刪除、時間最長先刪除等
(4).支持本地緩存文件名規則定義
歸納
1、Glide 默認的 Bitmap 格式是 RGB_565 格式,而 Picasso 默認的是 ARGB_8888 格式,這個內存開銷要小一半。
2、Glide 支持加載 Gif 動態圖,而 Picasso 不支持該特性。
3、在磁盤緩存方面,Picasso 只會緩存原始尺寸的圖片,而 Glide 緩存的是多種規格,也就意味着 Glide 會根據你 ImageView 的大小來緩存相應大小的圖片尺寸,比如你 ImageView 大小是200*200,原圖是 400*400 ,而使用 Glide 就會緩存 200*200 規格的圖,而 Picasso 只會緩存 400*400 規格的。這個改進就會導致 Glide 比 Picasso 加載的速度要快,畢竟少了每次裁剪重新渲染的過程。
4、Fresco確實強大,加載大圖Fresco最屌,但比較龐大,推薦在主要都是圖片的app中使用,一般的app使用Glide和Picasso就夠了!
5、Glide使自身內部已經實現了緩存策略,使得開發者擺脫Android圖片加載的瑣碎事務,專注邏輯業務的代碼。短短几行簡單明晰的代碼,即可完成大多數圖片從網絡(或者本地)加載、顯示的功能需求。
6、Unibersal-ImageLoader功能多,靈活使用配置