圖片加載涉及到圖片的緩存、圖片的處理、圖片的顯示等。而隨着市面上手機設備的硬件水平飛速發展,對圖片的顯示要求愈來愈高,稍微處理很差就會形成內存溢出等問題。不少軟件廠家的通用作法就是借用第三方的框架進行圖片加載。 開源框架的源碼仍是挺複雜的,但使用較爲簡單。大部分框架其實都差很少,配置稍微麻煩點,可是使用時通常只須要一行,顯示方法通常會提供多個重載方法,支持不一樣須要。這樣會減小很沒必要要的麻煩。同時,第三方框架的使用較爲方便,這大大的減小了工做量、提升了開發效率。本文主要介紹四種經常使用的圖片加載框架,分別是Fresco、ImageLoader、 Picasso、 Glide,包括他們各自的優缺點、使用步驟等等。android
首先看 Fresco, Fresco 是 Facebook 推出的開源圖片緩存工具,主要特色包括:兩個內存緩存加上 Native 緩存構成了三級緩存,支持流式,能夠相似網頁上模糊漸進式顯示圖片,對多幀動畫圖片支持更好,如 Gif、WebP。它的優勢是其餘幾個框架沒有的, 或者說是其餘幾個框架的短板。git
優勢:
1. 圖片存儲在安卓系統的匿名共享內存, 而不是虛擬機的堆內存中, 圖片的中間緩衝數據也存放在本地堆內存, 因此, 應用程序有更多的內存使用, 不會由於圖片加載而致使oom, 同時也減小垃圾回收器頻繁調用回收 Bitmap 致使的界面卡頓, 性能更高。
2. 漸進式加載 JPEG 圖片, 支持圖片從模糊到清晰加載。
3. 圖片能夠以任意的中心點顯示在 ImageView, 而不只僅是圖片的中心。
4. JPEG 圖片改變大小也是在 native 進行的, 不是在虛擬機的堆內存, 一樣減小 OOM。
5. 很好的支持 GIF 圖片的顯示。github
缺點:
1. 框架較大, 影響 Apk 體積
2. 使用較繁瑣算法
使用步驟:
1. 引入 Fresco,包括兩種方式,在線和離線。
在線引入依賴腳本形式,在dependencies中添加依賴,緩存
compile 'com.facebook.fresco:fresco:0.9.0'
引入離線引入,須要導入的arr包較多,包括:服務器
compile(name: 'drawee-0.9.0', ext: 'aar') compile(name: 'fbcore-0.9.0', ext: 'aar') compile(name: 'imagepipeline-0.9.0', ext: 'aar') compile(name: 'imagepipeline-base-0.9.0', ext: 'aar') compile files('libs/bolts-android-1.1.4.jar')
上面提到的aar其實就是lib module壓縮包的形式,包括.class和相關的資源文件,日常使用的jar僅僅包括.class文件。使用aar包時,還須要來到project `build.gradle`裏面, 在allprojects方法體加入 網絡
allprojects { repositories { jcenter() //add begin flatDir { dirs 'libs' } //add end }
2. 須要在程序入口方法裏面進行初始化。在oncreate方法中添加初始化語句。 併發
Fresco.initialize(context);
3. 在佈局文件中,須要使用圖片展現地方,使用它定義的控件app
<com.facebook.drawee.view.SimpleDraweeView android:id="@+id/iv_img" android:layout_width="150dp" android:layout_height="150dp" android:src="@mipmap/ic_launcher" fresco:fadeDuration="300" fresco:roundingBorderColor="#ccc" fresco:roundingBorderWidth="2dp"/>
4.設置靜態圖片,在代碼中具體寫以下代碼 框架
// 圖片加載 Uri uri = Uri.parse(data.url); holder.ivIcon.setImageURI(uri);
5. 設置gif圖片,在代碼中具體寫以下代碼
DraweeController gifController = Fresco.newDraweeControllerBuilder().setUri(uri) .setAutoPlayAnimations(true).build(); holder.ivIcon.setController(gifController);
ImageLoader是比較老的框架,是github社區上star最多的一個項目,能夠理解爲點贊最多滴,應該是最有名的一個國內不少知名軟件都用它包括淘寶京東聚划算等等。整個庫分爲 ImageLoaderEngine,Cache 及 ImageDownloader,ImageDecoder,BitmapDisplayer,BitmapProcessor 五大模塊,其中 Cache 分爲 MemoryCache 和 DiskCache 兩部分。簡單的講就是 ImageLoader 收到加載及顯示圖片的任務,並將它交給 ImageLoaderEngine,ImageLoaderEngine 分發任務到具體線程池去執行,任務經過 Cache 及 ImageDownloader 獲取圖片,中間可能通過 BitmapProcessor 和 ImageDecoder 處理,最終轉換爲Bitmap 交給 BitmapDisplayer 在 ImageAware中顯示。特色是穩定, 加載速度適中, 缺點在於不支持GIF圖片加載, 使用稍微繁瑣, 而且緩存機制沒有和 http 的緩存很好的結合, 徹底是本身的一套緩存機制。使用比較簡單,這個框架的github主頁上也有快速使用的步驟,基本上就是在application類裏的oncreate方法(整個程序開始時運行一次)中進行一下簡單的基本配置,能夠根據須要自行進行設定,懶得設定的話框架也提供了一個默認的配置,調用一個方法便可。基本上是配置一些相似於:緩存類型啊,緩存上限值啊,加載圖片的線程池數量啊等等。此外在頁面內顯示的時候還要設置一個顯示配置這個配置不一樣於基本配置,一個項目裏能夠根據須要建立多個配置對象使用,這個配置就比較具體了,能夠設置是否使用disk緩存(存到sd卡里通常),加載圖片失敗時顯示的圖片,默認圖片,圖片的色彩樣式等。ImageLoader和Volley圖片部分還包括其餘大部分圖片框架,基本上圖片處理都差很少,區別僅在於部分優化了,而優化方面UIL即Universal-Image-Loader框架作的最好,配置好之後,就是簡單的使用了,建立一個圖片加載對象,而後一行代碼搞定顯示圖片功能。參數通常是入你須要顯示的圖片url和imageview對象。
優勢:
1.支持下載進度監聽
2.能夠在 View 滾動中暫停圖片加載,經過 PauseOnScrollListener 接口能夠在 View 滾動中暫停圖片加載。
3.默認實現多種內存緩存算法 這幾個圖片緩存均可以配置緩存算法,不過 ImageLoader 默認實現了較多緩存算法,如 Size 最大先刪除、使用最少先刪除、最近最少使用、先進先刪除、時間最長先刪除等。
4.支持本地緩存文件名規則定義
使用步驟:
1. 在Application子類中的onCreate方法中初始化ImageLoaderConfiguration
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)// .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文件
4. 提供了豐富的緩存策略
內存緩存,如今咱們來看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(這個緩存類沒有任何的限制)
Picasso 是 Square 開源的項目,且他的主導者是 JakeWharton,因此廣爲人知。square公司,不少知名的開源也是該公司`android-times-square,leakcanary,okhttp,retrofit`。 Picasso的使用方便, 一行代碼完成加載圖片並顯示, 框架體積小。可是不支持 GIF, 而且它多是想讓服務器去處理圖片的縮放, 它緩存的圖片是未縮放的, 而且默認使用 ARGB_8888 格式緩存圖片, 緩存體積大。整個庫分爲 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 控制圖片的過時時間。
使用步驟:
1. 導入Picasso的jar包,添加依賴
2. 加載圖片
//圖片加載 Picasso.with(mContext) //建立Picasso .load(data.url) //傳入路徑 .fade(300) //淡化效果時長 .into(holder.ivIcon); //圖片加載到那個位置
Glide能夠說是 Picasso 的升級版, 有 Picasso 的優勢, 而且支持 GIF 圖片加載顯示, 圖片緩存也會自動縮放, 默認使用 RGB_565 格式緩存圖片, 是 Picasso 緩存體積的一半。谷歌爲咱們介紹了一個名叫 Glide 的圖片加載庫,做者是`bumptech`。這個庫被普遍的運用在google的開源項目中,包括2014年google I/O大會上發佈的官方app。整個庫分爲 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。
6.Glide 能夠經過 signature 或不使用本地緩存支持 url 過時
使用步驟
1. 導入Glide的jar包,添加依賴
2. 加載圖片
Glide.with(mContext) //建立Glide .load(data.url) //傳入路徑 .into(holder.ivIcon);//圖片加載到那個位置