Android中高效的顯示圖片之一 ——載入大圖

來源:互聯網
上載者:User

標籤:

在網上看了不少文章,發現還是官方文檔介紹最詳細,把重要的東西簡單摘要出來。詳細可看官方文檔地址 ( http://www.bangchui.org/read.php?tid=9 ) 。

 

在應用中顯示圖片,如果不多加小心,很容易就會使應用因為異常“java.lang.OutofMemoryError:bitmap size exceeds VM budget”而導致crash。在android中載入圖片需要一定的技巧性,主要是因為:

1.通常裝置資源有限,安卓裝置給每個應用只分配16M的空間。當然很多裝置都為應用設定了更高的記憶體,下面這個文檔的3.7節中有介紹不同螢幕裝置應用需要的最小記憶體(http://source.android.com/compatibility/downloads.html)。

2.圖片通常很占記憶體。例如Galxy Nexus相機解析度高達2592x1936,如果圖片配置為ARGB_8888(2.3以後預設配置),載入一張照片就需要19M記憶體(2592x1936x4 bytes),會很快消耗完一個應用的記憶體。

3.安卓的UI中通常需要一下載入多張圖片,如ListView,ViewPager。

 

本文主要介紹怎麼高效地載入大圖而不至於使你的應用記憶體溢出。大圖通常會比螢幕尺寸大很多,然而載入一個高解析度的圖片並不能帶來多少視覺體驗,通過下面兩步可以載入一個壓縮尺寸的圖片就節省記憶體。

第一步,讀取圖片尺寸和類型。

BitmapFactory類提供了多個decoding方法(decodeByteArray(), decodeFile(), decodeResource(), 等)使可以通過各種資料來源建立Bitmap,這些方法會在bitmap構造時申請記憶體,對於大圖,這樣會很容易導致記憶體溢出。每種decode方法都有一個額外的標誌參數BitmapFactory.Options,設定它的inJustDecodeBounds屬性為true,可以避免decode時分配記憶體,返回的Bitmap對象是一個null值,但能得到圖片的原始高度、寬度和格式(儲存在option的outWidth,outHeight,outMimeType中)。通過這種方式,可以在構造圖片前獲得圖片屬性。下面是範例程式碼:

 

[java] view plaincopy
  1. BitmapFactory.Options options = new BitmapFactory.Options();    
  2. options.inJustDecodeBounds = true;    
  3. BitmapFactory.decodeResource(getResources(), R.id.myimage, options);    
  4. int imageHeight = options.outHeight;    
  5. int imageWidth = options.outWidth;    
  6. String imageType = options.outMimeType;    

 

為了避免記憶體溢出,最好在載入圖片前都對尺寸做檢查,除非你保證源圖片沒有大圖。

第二步,載入縮小後的圖片到記憶體。

現在知道了原圖片的尺寸,根據實際情況決定你要載入它縮小多少倍後的圖片。例如你用一個128x96的ImageView顯示一張1024x768的原圖,根本沒有必要把原圖讀載入到記憶體。載入一張縮小後的圖片到記憶體,只需要把BitmapFactory.Options對象的inSampleSize設為true,然後給inSampleSize設一個值就行了(可以理解inSampleSize為n,圖片就縮小到1/n大小)。

下面是一段載入圖片的一段範例程式碼

 

[java] view plaincopy
  1. public static int calculateInSampleSize(  
  2.             BitmapFactory.Options options, int reqWidth, int reqHeight) {  
  3.     // Raw height and width of image  
  4.     final int height = options.outHeight;  
  5.     final int width = options.outWidth;  
  6.     int inSampleSize = 1;  
  7.   
  8.     if (height > reqHeight || width > reqWidth) {  
  9.         if (width > height) {  
  10.             inSampleSize = Math.round((float)height / (float)reqHeight);  
  11.         } else {  
  12.             inSampleSize = Math.round((float)width / (float)reqWidth);  
  13.         }  
  14.     }  
  15.     return inSampleSize;  
  16. }  



 

 

[java] view plaincopy
  1. public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,  
  2.         int reqWidth, int reqHeight) {  
  3.   
  4.     // First decode with inJustDecodeBounds=true to check dimensions  
  5.     final BitmapFactory.Options options = new BitmapFactory.Options();  
  6.     options.inJustDecodeBounds = true;  
  7.     BitmapFactory.decodeResource(res, resId, options);  
  8.   
  9.     // Calculate inSampleSize  
  10.     options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);  
  11.   
  12.     // Decode bitmap with inSampleSize set  
  13.     options.inJustDecodeBounds = false;  
  14.     return BitmapFactory.decodeResource(res, resId, options);  
  15. }  

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.