Android 常見的圖片載入架構詳細介紹_Android

來源:互聯網
上載者:User

Android 常見的圖片載入架構

圖片載入涉及到圖片的緩衝、圖片的處理、圖片的顯示等。而隨著市面上手機裝置的硬體水平飛速發展,對圖片的顯示要求越來越高,稍微處理不好就會造成記憶體溢出等問題。很多軟體廠家的通用做法就是借用第三方的架構進行圖片載入。 開源架構的源碼還是挺複雜的,但使用較為簡單。大部分架構其實都差不多,配置稍微麻煩點,但是使用時一般只需要一行,顯示方法一般會提供多個重載方法,支援不同需要。這樣會減少很不必要的麻煩。同時,第三方架構的使用較為方便,這大大的減少了工作量、提高了開發效率。本文主要介紹四種常用的圖片載入架構,分別是Fresco、ImageLoader、 Picasso、 Glide,包括他們各自的優缺點、使用步驟等等。

      首先看 Fresco, Fresco 是 Facebook 推出的開源圖片緩衝工具,主要特點包括:兩個記憶體緩衝加上 Native 緩衝構成了三級緩衝,支援流式,可以類似網頁上模糊漸進式顯示圖片,對多幀動畫圖片支援更好,如 Gif、WebP。它的優點是其他幾個架構沒有的, 或者說是其他幾個架構的短板。

      優點:

         1. 圖片儲存在安卓系統的匿名共用記憶體, 而不是虛擬機器的堆記憶體中, 圖片的中間緩衝資料也存放在本地堆記憶體, 所以, 應用程式有更多的記憶體使用量, 不會因為圖片載入而導致oom, 同時也減少記憶體回收行程頻繁調用回收 Bitmap 導致的介面卡頓, 效能更高。
         2. 漸進式載入 JPEG 圖片, 支援圖片從模糊到清晰載入。
         3. 圖片可以以任意的中心點顯示在 ImageView, 而不僅僅是圖片的中心。
         4. JPEG 圖片改變大小也是在 native 進行的, 不是在虛擬機器的堆記憶體, 同樣減少 OOM。
         5. 很好的支援 GIF 圖片的顯示。

    缺點:

         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. 在布局檔案中,需要使用圖片展示地方,使用它定義的控制項

<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 = "yun_qi_img/"; // 網狀圖片  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 緩衝體積的一半。Google為我們介紹了一個名叫 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);//圖片載入到那個位置

感謝閱讀,希望能協助到大家,謝謝大家對本站的支援!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.