Android圖片載入庫的理解

來源:互聯網
上載者:User

標籤:

前言       這是“基礎自測”系列的第三篇文章,以Android開發需要熟悉的20個技術點為切入點,本篇重點講講Android中的ImageLoader這個庫的一些理解,在Android上最讓人頭疼是從網路中擷取圖片,顯示,回收,任何一個環節有問題都可能直接OOM,當需要載入大量的圖片的時候,每當快速滑,有時候會很卡,甚至會因為記憶體溢出而崩潰。這裡講解的庫是:Universal_Image_Loader。內容目錄
  • ImageLoader設計原理
  • ImageLoader流程圖
  • ImageLoader的使用
  • ImageLoader最佳化
  • Fresco介紹
  • 圖片策略最佳化
  • 小結
ImageLoader設計原理

ImageLoader的工作原理:在顯示圖片的時,它會先在記憶體中尋找,如果沒有就去本地尋找,如果還沒有,就開一個新的線程去下載這張圖片,下載成功會把圖片同時緩衝在記憶體和本地。

我們在基於這個原理,在每次退出一個頁面時候,把ImageLoader記憶體中緩衝全部清除,這樣就節省了大量記憶體,反正下次再用到的時候從本地再取出來就行了。需要說明的是,由於ImageLoader對圖片是軟引用的形式,所以在記憶體中的圖片會存在記憶體不足的時候被系統回收。總設計圖:ImageLoader流程圖

ImageLoader的使用ImageLoader由三大組件組成:
  1. ImagaLoaderConfiguaration——對圖片緩衝進行總體配置,包含記憶體緩衝的大小,本機快取的大小和位置、日誌、下載策略(FIFO還是LIFO)等。
  2. ImageLoader——一般使用displayImage來把URL對應的圖片顯示在ImageView上。
  3. DisplayImageOptions——在每個頁面需要顯示圖片的地方,控制如何顯示的細節,比如指定下載時的預設圖、是否將緩衝放到記憶體或本地磁碟。

從三者的協作關係上看,他們有點像廚房規定、廚師、客戶個人口味之間的關係。ImageLoaderConfiguration就像是廚房裡面的規定,每一個廚師要怎麼著裝,要怎麼保持廚房的乾淨,這是針對每一個廚師都適用的規定,而且不允許個人化改變。ImageLoader就像是具體做菜的廚師,負責具體菜譜的製作。DisplayImageOptions就像每個客戶的偏好,根據客戶是重口味還是清淡,每一個imageLoader根據DisplayImageOptions的要求具體執行。

ImagaLoaderConfiguaration範例程式碼:
// DON‘T COPY THIS CODE TO YOUR PROJECT! This is just example of ALL options using.// See the sample project how to use ImageLoader correctly.File cacheDir =StorageUtils.getCacheDirectory(context);ImageLoaderConfiguration config =newImageLoaderConfiguration.Builder(context)        .memoryCacheExtraOptions(480, 800) // default = device screen dimensions        .diskCacheExtraOptions(480, 800, null)        .taskExecutor(...)        .taskExecutorForCachedImages(...)        .threadPoolSize(3) // default        .threadPriority(Thread.NORM_PRIORITY-2) // default        .tasksProcessingOrder(QueueProcessingType.FIFO) // default        .denyCacheImageMultipleSizesInMemory()        .memoryCache(newLruMemoryCache(2*1024*1024))        .memoryCacheSize(2*1024*1024)        .memoryCacheSizePercentage(13) // default        .diskCache(newUnlimitedDiskCache(cacheDir)) // default        .diskCacheSize(50*1024*1024)        .diskCacheFileCount(100)        .diskCacheFileNameGenerator(newHashCodeFileNameGenerator()) // default        .imageDownloader(newBaseImageDownloader(context)) // default        .imageDecoder(newBaseImageDecoder()) // default        .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default        .writeDebugLogs()        .build();
可以看到ImagaLoaderConfiguaration的職責就是記錄相關的配置,它的內部就是一些欄位的集合。DisplayImageOptions

每一個ImageLoader.displayImage(...)都可以使用DisplayImageOptions,具體配置代碼如下:

// DON‘T COPY THIS CODE TO YOUR PROJECT! This is just example of ALL options using.// See the sample project how to use ImageLoader correctly.DisplayImageOptions options = new DisplayImageOptions.Builder()        .showImageOnLoading(R.drawable.ic_stub) // resource or drawable        .showImageForEmptyUri(R.drawable.ic_empty) // resource or drawable        .showImageOnFail(R.drawable.ic_error) // resource or drawable        .resetViewBeforeLoading(false)  // default        .delayBeforeLoading(1000)        .cacheInMemory(false) // default        .cacheOnDisk(false) // default        .preProcessor(...)        .postProcessor(...)        .extraForDownloader(...)        .considerExifParams(false) // default        .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default        .bitmapConfig(Bitmap.Config.ARGB_8888) // default        .decodingOptions(...)        .displayer(new SimpleBitmapDisplayer()) // default        .handler(new Handler()) // default        .build();
ImageLoader最終使用時候,簡單幾句就行了,傳入一個ImageView控制項
ImageLoader imageLoader = ImageLoader.getInstance(); // Get singleton instance// Load image, decode it to Bitmap and display Bitmap in ImageView (or any other view //  which implements ImageAware interface)imageLoader.displayImage(imageUri, imageView);
又或者直接
// Load image, decode it to Bitmap and return Bitmap to callbackimageLoader.loadImage(imageUri, new SimpleImageLoadingListener() {    @Override    public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {        // Do whatever you want with Bitmap    }});
ImageLoader最佳化儘管ImageLoader很強大,但一直把圖片緩衝在記憶體中,會導致記憶體佔用過高。雖然對圖片的引用是軟引用,軟引用在記憶體不夠的時候會被GC,但我們還是希望減少GC的次數,所以要經常手動清理ImageLoader中的緩衝。比如,我們經常在做項目的時候,會有一個AppBaseActivity的基類,這樣我們可以在基類的onDestroy方法中,執行ImageLoader的clearMemoryCache方法,以確保頁面銷毀時,把為了顯示這個頁面而增加的記憶體緩衝清除,這樣即使到了下個頁面要複用之前載入過的圖片,雖然記憶體沒有了,根據ImageLoader的緩衝策略,在本地磁碟上還是能被找到的。比如: 
protected void onDestroy() {        //回收該頁面緩衝在記憶體的圖片        imageLoader.clearMemoryCache();         super.onDestroy();}
Fresco介紹簡介:

Fresco 是一個強大的圖片載入組件。它是Facebook開源的圖片載入庫

Fresco 中設計有一個叫做 image pipeline 的模組。它負責從網路,從本地檔案系統,本地資源載入圖片。為了最大限度節省空間的和CPU時間,它含有3級緩衝設計(2級記憶體,1級檔案)。

Fresco 中設計有一個叫做 Drawees 模組,方便地顯示loading圖,當圖片不再顯示在螢幕上時,及時地釋放記憶體和空間佔用。

Fresco 支援 Android2.3(API level 9) 及其以上系統。

 

流程圖:  原理:Fresco 設計了image pipeline 的概念,它負責先後檢查記憶體,磁碟檔案,如果都沒有再老老實實從網路下載圖片。主要有個三層緩衝的概念第一層:Bitmap緩衝在Android 5.0系統中,考慮到記憶體管理有了很大改進,所以 Bitmap緩衝位於Java的heap中,而在Android 4.X或更低的系統中,Bitmap緩衝位於ashmem中,而不是位於Java的heap中,這意味著圖片的建立和回收不會引發過多的GC,從而讓APP啟動並執行更快。第二層:記憶體緩衝記憶體緩衝中儲存了圖片的原始壓縮格式,從記憶體緩衝中取出的圖片,在顯示前必須先解碼,當APP切換到後台時,記憶體緩衝也會被清空。第三層:磁碟緩衝又名本機快取,磁碟緩衝中儲存的也是圖片的原始壓縮格式,在使用前也要先解碼,當APP切換到後台時,磁碟緩衝不會丟失,即使關機也不會。 使用:

為了下載網狀圖片,請確保在 AndroidManifest.xml 中有以下許可權:

<uses-permission android:name="android.permission.INTERNET"/>

在 Application 初始化時,在應用調用 setContentView() 之前,進行初始化:

Fresco.initialize(context); 

在xml布局檔案中, 加入命名空間:

<!-- 其他元素 --><LinearLayout     xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:fresco="http://schemas.android.com/apk/res-auto">加入SimpleDraweeView:<com.facebook.drawee.view.SimpleDraweeView    android:id="@+id/my_image_view"    android:layout_width="20dp"    android:layout_height="20dp"    fresco:placeholderImage="@drawable/my_drawable"  />

開始載入圖片

Uri uri = Uri.parse("https://raw.githubusercontent.com/facebook/fresco/gh-pages/static/fresco-logo.png");SimpleDraweeView draweeView = (SimpleDraweeView) findViewById(R.id.my_image_view);draweeView.setImageURI(uri);
圖片策略最佳化我們這裡說的圖片,是根據服務端的介面返回的圖片URL地址開啟一個線程下載到APP本地並顯示的,很多APP崩潰的原因就是圖片的問題沒處理好。那麼就有一些相關解決方案策略,如下。
  1. 要確保下載的每張圖,都符合ImageView控制項的大小。可以事先準備很多套不同的解析度的圖片,然後每次根據URL請求圖片時,都要額外在URL上加兩個參數,width和height,從而要求伺服器返回其中某一個張圖,比如:http://www.aaa.com/a.png?width=100&height=50
  2. 低流量模式。在2G和3G網路環境下,我們應該適當降低圖片的品質,降低圖片品質,相應的圖片大小也會降低,簡稱低流量模式,比如在請求網址中再添加一個參數,叫做quality,在2G網路下這個值為50%,在3G網路情況下,這個值為70%,這樣就會將JPG圖片品質降低為50%或70%。
  3. 極速模式。發現在2G和3G網路環境下,大部分使用者對圖片不感興趣,我們可以設計一些只有文字的頁面,這種頁面稱呼為極速模式,以節省流量。
小結

本篇主要介紹了第三方圖片載入庫的原理和使用方法,特別是ImageLoader的介紹,因為圖片顯示在APP中是很常見的應用情境,況且ImageLoader已經封裝好了一些類和方法。我們可以直接拿來用了。而不用重複去寫了。如果自己去寫一個的話,這方面的程式還是比較麻煩的,要考慮多線程緩衝,記憶體溢出等很多方面,再說這麼多程式都在用,說明穩定性還是可靠的,類似這種工具類能用穩定成熟的,我們作為一名開發人員,專註度還是在應用業務開發上。

基礎自測源於想對自我掌握的基本Android開發基礎點熟悉程度,所以就準備從以下20個基礎點入手,鞏固下基礎的知識點。1,ProGuard代碼混淆2,講講Handler+Looper+MessageQueue關係3,Android圖片載入庫理解

 

Android圖片載入庫的理解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.