一. 四大圖片緩存基本信息
該圖是我在網上找的,也許不是最新的,具體的信息以我下邊給的為主
為了方便我也就copy了一下,只是希望大家能夠看得更清楚:
Universal ImageLoader 是很早開源的圖片緩存,在早期被很多應用使用。
是 Square 開源的項目,且他的主導者是 JakeWharton,所以廣為人知。
具體使用:
1:在Application子類中的onCreate方法中初始化ImageLoaderConfiguration
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)//Picasso
.threadPriority(Thread.NORM_PRIORITY - 2)//
.denyCacheImageMultipleSizesInMemory()//
.diskCacheFileNameGenerator(new Md5FileNameGenerator())//
.diskCacheSize(50 * 1024 * 1024) // 50 Mb
.memoryCache(new LruMemoryCache(4 * 1024 * 1024)).tasksProcessingOrder(QueueProcessingType.LIFO)//
.writeDebugLogs() // Remove for release app
.build();
// Initialize ImageLoader with configuration.
ImageLoader.getInstance().init(config);
2:再具體的地方使用:
圖片加載
ImageLoader.getInstance().displayImage(data.url, holder.ivIcon);
DisplayImageOptions option = new DisplayImageOptions.Builder()
.resetViewBeforeLoading(true)
.cacheOnDisk(true)
.imageScaleType(ImageScaleType.EXACTLY)
.bitmapConfig(Bitmap.Config.RGB_565)
.considerExifParams(true)
.displayer(new FadeInBitmapDisplayer(300))
.build();
ImageLoader.getInstance().displayImage(data.url, holder.ivIcon, option);
3:加載各種圖片的格式:
String imageUri = "http://site.com/image.png"; // 網絡圖片
String imageUri = "file:///mnt/sdcard/image.png"; //SD卡圖片
String imageUri = "content://media/external/audio/albumart/13"; // 媒體文件夾
String imageUri = "assets://image.png"; // assets
String imageUri = "drawable://" + R.drawable.image; // drawable文件
提供了豐富的緩存策略
內存緩存
現在我們來看Universal-Image-Loader有哪些內存緩存策略
1. 只使用的是強引用緩存
LruMemoryCache(這個類就是這個開源框架默認的內存緩存類,緩存的是bitmap的強引用,下面我會從源碼上面分析這個類)
2.使用強引用和弱引用相結合的緩存有
UsingFreqLimitedMemoryCache(如果緩存的圖片總量超過限定值,先刪除使用頻率最小的bitmap)
LRULimitedMemoryCache(這個也是使用的lru算法,和LruMemoryCache不同的是,他緩存的是bitmap的弱引用)
FIFOLimitedMemoryCache(先進先出的緩存策略,當超過設定值,先刪除最先加入緩存的bitmap)
LargestLimitedMemoryCache(當超過緩存限定值,先刪除最大的bitmap對象)
LimitedAgeMemoryCache(當 bitmap加入緩存中的時間超過我們設定的值,將其刪除)
3.只使用弱引用緩存
WeakMemoryCache(這個類緩存bitmap的總大小沒有限制,唯一不足的地方就是不穩定,緩存的圖片容易被回收
硬盤緩存
FileCountLimitedDiscCache(可以設定緩存圖片的個數,當超過設定值,刪除掉最先加入到硬盤的文件)
LimitedAgeDiscCache(設定文件存活的最長時間,當超過這個值,就刪除該文件)
TotalSizeLimitedDiscCache(設定緩存bitmap的最大值,當超過這個值,刪除最先加入到硬盤的文件)
UnlimitedDiscCache(這個緩存類沒有任何的限制)
下面我們可以簡單的看一下Lru這個到底是如何實現上邊的那些緩存的:
Lru的上邊的注解寫的很清楚:同時不知道大家有沒有注意到Lru使用的LinkHasMap的同時里面傳了一個非常重要的參數:
/**
* Constructs an empty <tt>LinkedHashMap</tt> instance with the
* specified initial capacity, load factor and ordering mode.
*
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
* @param accessOrder the ordering mode - <tt>true</tt> for
* access-order, <tt>false</tt> for insertion-order
* @throws IllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive
*/
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
LRU是Least Recently Used的縮寫,即最近最少使用頁面置換[算法,是為虛擬頁式存儲管理服務的,是根據頁面調入內存后的使用情況進行決策了。由于無法預測各頁面將來的使用情況,只能利用“最近的過去”作為“最近的將來”的近似,因此,LRU算法就是將最近最久未使用的頁面予以淘汰。
false: 基于插入順序 true: 基于訪問順序
所以如果有一張圖片一直在最地而且一直都未唄使用的話那么他就很好的記錄的他的順利當內存大小不足的直接干掉那張最不常用的圖片,說了那么多終于可以說說他的特點了:
其特點:
(1)可以自動檢測 adapter 的重用并取消之前的下載
(2)圖片變換
(3)可以加載本地資源
(4)可以設置占位資源
(5)支持 debug 模式
Glide介紹:
谷歌為我們介紹了一個名叫 Glide 的圖片加載庫,。這個庫被廣泛的運用在google的開源項目中,包括2014年google I/O大會上發布的官方app
下面是谷歌的一段自我解說關于Glide:
Glide is a fast and efficient open source media management and image loading framework for Android that wraps media decoding, memory and disk caching, and resource pooling into a simple and easy to use interface.
簡明的來說就是Glide 是一個快速并且高效的android封裝庫,支持內存緩存和磁盤緩存,
Glide鏈接地址
Glide的特點:
(1) GIF 動畫的解碼
(2) 本地視頻劇照的解碼
(3) 支持縮略圖
(4) Activity 生命周期的集成
(5) 轉碼的支持
(6) 動畫的支持
(7) OkHttp 和 Volley 的支持
Glide的最基本使用:
You can download a jar from GitHub's releases page.
Or use Gradle:
repositories { mavenCentral() // jcenter() works as well because it pulls from Maven Central}dependencies { compile 'com.github.bumptech.glide:glide:3.7.0' compile 'com.android.support:support-v4:19.1.0'}
// For a simple view:
@Override public void onCreate(Bundle savedInstanceState) {
...
ImageView imageView = (ImageView) findViewById(R.id.my_image_view);
Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);
}
**Fresco **
鏈接地址
說實話因為的我項目我感覺暫時用不上這么強大的庫所以暫時還未用過
不過如果你們想要了解的話這邊提供一個鏈接
具體使用步驟鏈接
所以我也就不在貼代碼展示了
****----___
Fresco 是 Facebook 也是很早開源的圖片緩存,主要特點包括:
(1) 兩個內存緩存加上 Native 緩存構成了三級緩存
(2) 支持流式,可以類似網頁上模糊漸進式顯示圖片
(3) 對多幀動畫圖片支持更好,如 Gif、WebP
(4) 我覺得它主要是針對大工程量使用;
二、基本概念
在正式對比前,先了解幾個圖片緩存通用的概念:
(1) RequestManager:請求生成和管理模塊
(2) Engine:引擎部分,負責創建任務(獲取數據),并調度執行
(3) GetDataInterface:數據獲取接口,負責從各個數據源獲取數據。
比如 MemoryCache 從內存緩存獲取數據、DiskCache 從本地緩存獲取數據,下載器從網絡獲取數據等。
(4) Displayer:資源(圖片)顯示器,用于顯示或操作資源。
比如 ImageView,這幾個圖片緩存都不僅僅支持 ImageView,同時支持其他 View 以及虛擬的 Displayer 概念。
(5) Processor 資源(圖片)處理器
負責處理資源,比如旋轉、壓縮、截取等。
以上概念的稱呼在不同圖片緩存中可能不同,比如 Displayer 在 ImageLoader 中叫做 ImageAware,在 Picasso 和 Glide 中叫做 Target。
三、共同優點
1. 使用簡單
都可以通過一句代碼可實現圖片獲取和顯示。
2. 可配置度高,自適應程度高
圖片緩存的下載器(重試機制)、解碼器、顯示器、處理器、內存緩存、本地緩存、線程池、緩存算法等大都可輕松配置。
自適應程度高,根據系統性能初始化緩存配置、系統信息變更后動態調整策略。
比如根據 CPU 核數確定最大并發數,根據可用內存確定內存緩存大小,網絡狀態變化時調整最大并發數等。
3. 多級緩存
都至少有兩級緩存、提高圖片加載速度。
4. 支持多種數據源
支持多種數據源,網絡、本地、資源、Assets 等
5. 支持多種 Displayer
不僅僅支持 ImageView,同時支持其他 View 以及虛擬的 Displayer 概念。
其他小的共同點包括支持動畫、支持 transform 處理、獲取 EXIF 信息等。
四、ImageLoader 設計及優點
總體設計及流程
上面是 ImageLoader 的總體設計圖。整個庫分為 ImageLoaderEngine,Cache 及 ImageDownloader,ImageDecoder,BitmapDisplayer,BitmapProcessor 五大模塊,其中 Cache 分為 MemoryCache 和 DiskCache 兩部分。
簡單的講就是 ImageLoader 收到加載及顯示圖片的任務,并將它交給 ImageLoaderEngine,ImageLoaderEngine 分發任務到具體線程池去執行,任務通過 Cache 及 ImageDownloader 獲取圖片,中間可能經過 BitmapProcessor 和 ImageDecoder 處理,最終轉換為Bitmap 交給 BitmapDisplayer 在 ImageAware 中顯示。-
ImageLoader 優點
(1) 支持下載進度監聽
(2) 可以在 View 滾動中暫停圖片加載
通過 PauseOnScrollListener 接口可以在 View 滾動中暫停圖片加載。
(3) 默認實現多種內存緩存算法這幾個圖片緩存都可以配置緩存算法,不過 ImageLoader 默認實現了較多緩存算法,如 Size 最大先刪除、使用最少先刪除、最近最少使用、先進先刪除、時間最長先刪除等。
(4) 支持本地緩存文件名規則定義
五、Picasso 設計及優點
總體設計及流程
上面是 Picasso 的總體設計圖。整個庫分為 Dispatcher,RequestHandler 及 Downloader,PicassoDrawable 等模塊。
Dispatcher 負責分發和處理 Action,包括提交、暫停、繼續、取消、網絡狀態變化、重試等等。
簡單的講就是 Picasso 收到加載及顯示圖片的任務,創建 Request 并將它交給 Dispatcher,Dispatcher 分發任務到具體 RequestHandler,任務通過 MemoryCache 及 Handler(數據獲取接口) 獲取圖片,圖片獲取成功后通過 PicassoDrawable 顯示到 Target 中。
需要注意的是上面 Data 的 File system 部分,Picasso 沒有自定義本地緩存的接口,默認使用 http 的本地緩存,API 9 以上使用 okhttp,以下使用 Urlconnection,所以如果需要自定義本地緩存就需要重定義 Downloader。-
Picasso 優點
(1) 自帶統計監控功能
支持圖片緩存使用的監控,包括緩存命中率、已使用內存大小、節省的流量等。
(2) 支持優先級處理
每次任務調度前會選擇優先級高的任務,比如 App 頁面中 Banner 的優先級高于 Icon 時就很適用。
(3) 支持延遲到圖片尺寸計算完成加載
(4) 支持飛行模式、并發線程數根據網絡類型而變
手機切換到飛行模式或網絡類型變換時會自動調整線程池最大并發數,比如 wifi 最大并發為 4, 4g 為 3,3g 為 2。
這里 Picasso 根據網絡類型來決定最大并發數,而不是 CPU 核數。
(5) “無”本地緩存
無”本地緩存,不是說沒有本地緩存,而是 Picasso 自己沒有實現,交給了 Square 的另外一個網絡庫 okhttp 去實現,這樣的好處是可以通過請求 Response Header 中的 Cache-Control 及 Expired 控制圖片的過期時間。
六、Glide 設計及優點
總體設計及流程
上面是 Glide 的總體設計圖。整個庫分為 RequestManager(請求管理器),Engine(數據獲取引擎)、 Fetcher(數據獲取器)、MemoryCache(內存緩存)、DiskLRUCache、Transformation(圖片處理)、Encoder(本地緩存存儲)、Registry(圖片類型及解析器配置)、Target(目標) 等模塊。
簡單的講就是 Glide 收到加載及顯示資源的任務,創建 Request 并將它交給RequestManager,Request 啟動 Engine 去數據源獲取資源(通過 Fetcher ),獲取到后 Transformation 處理后交給 Target。
Glide 依賴于 DiskLRUCache、GifDecoder 等開源庫去完成本地緩存和 Gif 圖片解碼工作。-
Glide 優點
(1) 圖片緩存->媒體緩存
Glide 不僅是一個圖片緩存,它支持 Gif、WebP、縮略圖。甚至是 Video,所以更該當做一個媒體緩存。
(2) 支持優先級處理
(3) 與 Activity/Fragment 生命周期一致,支持 trimMemory
Glide 對每個 context 都保持一個 RequestManager,通過 FragmentTransaction 保持與 Activity/Fragment 生命周期一致,并且有對應的 trimMemory 接口實現可供調用。
(4) 支持 okhttp、Volley
Glide 默認通過 UrlConnection 獲取數據,可以配合 okhttp 或是 Volley 使用。實際 ImageLoader、Picasso 也都支持 okhttp、Volley。
(5) 內存友好
① Glide 的內存緩存有個 active 的設計
從內存緩存中取數據時,不像一般的實現用 get,而是用 remove,再將這個緩存數據放到一個 value 為軟引用的 activeResources map 中,并計數引用數,在圖片加載完成后進行判斷,如果引用計數為空則回收掉。
② 內存緩存更小圖片
Glide 以 url、view_width、view_height、屏幕的分辨率等做為聯合 key,將處理后的圖片緩存在內存緩存中,而不是原始圖片以節省大小
③ 與 Activity/Fragment 生命周期一致,支持 trimMemory
④ 圖片默認使用默認 RGB_565 而不是 ARGB_888
雖然清晰度差些,但圖片更小,也可配置到 ARGB_888。
其他:Glide 可以通過 signature 或不使用本地緩存支持 url 過期
七、匯總
三者總體上來說,ImageLoader 的功能以及代理容易理解長度都一般。
Picasso 代碼雖然只在一個包下,沒有嚴格的包區分,但代碼簡單、邏輯清晰,一兩個小時就能叫深入的了解完。
Glide 功能強大,Glide的源碼也是最難理解的,但是如果只是簡單使用的還是挺方便的,現在我基本上都是在使用Glide;