Android高效開發(一)—合理使用圖片資源

前言

在Android開發中,咱們不免會遇到加載圖片的場景。不論是網絡圖片、資源圖片或者是SD卡中的圖片,都須要加載到內存中使用。若是不能合理處理圖片,可能會致使OOM的問題或者其餘性能問題,接下就討論下Android中圖片資源處理的幾種經常使用的方式。android

Resource中的圖片資源的處理

在Android中開發的時候都會用到不少圖片素材,對於某些背景圖片、各類圖標或者其餘一些提示圖片咱們一般會放到res目錄中的drawable中。緩存

咱們知道在res目錄下有不少drawable目錄,好比:drawable、drawable-hdpi、drawable-mdpi等。這些目錄對應了不一樣密度的屏幕,在不一樣密度的屏幕下會優先從對應目錄下取圖片資源。網絡

目錄名稱 密度(Density)
res/drawable 0
res/drawable-ldpi 120
res/drawable-mdpi 160
res/drawable-hdpi 240
res/drawable-xhdpi 320
res/drawable-xxdpi 480

這六種目錄表明了目前市面上Android機型不一樣的6中密度的屏幕。框架

注意:res/drawable目錄的密度爲0,不是說有機型的屏幕密度爲0。這是默認密度,在不一樣機型下默認密度不同。ide

Android如何找到res中圖片資源

Android在加載資源圖片時,會先獲取當前設備的屏幕密度,而後根據屏幕密度去找圖片資源。若是沒有在對應的文件夾下找到圖片資源,就會採起就近原則,從與屏幕密度最相近的圖片資源目錄獲取。若是都沒有就只能從默認的資源目錄下獲取(也就是res/drawable)。性能

在獲取到圖片資源時,若是密度不匹配,Android會對圖片進行處理。好比在res/drawable-mdpi找到了圖片,可是設備屏幕密度是xxdpi的,那麼Android就會按照3倍大小縮放這張圖片。根據圖片內存的計算公式(圖片高度 x 圖片寬度 x 一個像素佔用的內存大小)。好比:一張800x480的圖片原來佔用內存大約是1.46M,增長3倍後圖片是3200x1920,佔用內存大約是23M。而通常Android系統分配給每一個進程的內存也才一百多M,在低配手機中很容易就產生OOM。學習

如何處理

針對上面的狀況,如何處理資源文件呢?由於Android拿到低密度的圖片時,在高密度設備會將其放大。因此在添加資源文件時,應該優先使用高品質圖片從高密度的目錄往下放。優化

Bitmap圖片的處理

Bitmap類型的圖片也是在開發中常常用到的。對於Bitmap圖片若是不加處理直接使用的話,也很容易致使OOM。由於會有一些佔用很大的圖片被加載到內存中,而真正的需求可能並不須要這麼大的圖片。spa

接下來的內容大多來自於Google推薦的一種處理Bitmap圖片的方法。連接在下面,感興趣的同窗也能夠直接閱讀文檔。code

developer.android.com/topic/perfo…

在Google的方案中,主要的思想是按需加載Bitmap。所謂的按需加載,就是根據圖片的尺寸和要加載圖片的ImageView的尺寸對Bitmap進行壓縮處理。

獲取Bitmap圖片的尺寸

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
複製代碼

上面的代碼會獲取到Bitmap圖片的寬、高、MimeType。同時這裏有個參數是比較重要的,inJustDecodeBounds這個參數設爲true的時候不會在內存中分配Bitmap的空間,只是獲取到了Bitmap圖片的寬高等信息。

計算壓縮比例

public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
        //若是Bitmap圖片寬高大於ImageView寬高,就縮放圖片
        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        //計算縮放比例
        while ((halfHeight / inSampleSize) >= reqHeight
                && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}
複製代碼

上面的代碼經過圖片的尺寸計算Bitmap圖片的縮放比例。最終獲得的結果inSampleSize就是須要縮放的比例。

得到圖片

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}
複製代碼

這一步是獲取獲得最終的Bitmap圖片,能夠看到BitmapFactory.Options options的inSampleSize是縮放比例,在獲取圖片以前,將inJustDecodeBounds設置爲false,而後再次調用decode方法就得到了最終的Bitma對象。

使用圖片加載框架

在處理圖片時,特別是網絡圖片若是咱們想要高效的利用圖片資源。這個時候使用圖片加載框架是一個很好的選擇。好比:Glide框架。這也是Google推薦的圖片加載框架。

圖片加載框架不只能幫助咱們處理圖片。同時還能經過緩存複用圖片,提升圖片的利用率。

總結

在Android開發中,圖片的處理幾乎是因此應用都要面對的場景,可以瞭解一些圖片的優化的小技巧,可以提升咱們在開發中的效率與質量。若是各位同窗有更好的方法,歡迎在評論區討論,你們共同窗習。

相關文章
相關標籤/搜索