摘要:我知道最近世麟心情是錯綜復(fù)雜,但還好的是絕大多數(shù)程序員都是特別有善心的。如果圖像數(shù)據(jù)較大就會造成對象申請的內(nèi)存較多,如果圖像過多就會造成內(nèi)存不夠用自然就會出現(xiàn)的現(xiàn)象。第二次將設(shè)置為再次調(diào)用函數(shù)時就能生成了。
目錄介紹
01.先看一個需求分析案例
02.Bitmap占用內(nèi)存介紹
03.影響B(tài)itmap占用內(nèi)存因素
04.圖像加載的方式
05.加載圖像內(nèi)存去哪里了
06.具體實現(xiàn)加載圖片步驟
希望世麟兄弟母親盡快好起來和南塵(世麟)認識與網(wǎng)絡(luò),估計好多程序員都看過他的文章,我也是。雖然沒有見過面,但是微信聊過多次,感覺人非常不錯。都具有共同的愛好,喜歡寫技術(shù)博客和開源項目,算得上同道中人。
對于這次他遇到的事情,我的確很佩服他那種承擔的責任和勇氣。對于任何一個出身一般的人來說,大多數(shù)家庭都是難以承擔疾病所帶來的費用,即使有勇氣承擔,那經(jīng)濟上也的確讓人壓力很大,如果可以盡綿薄之力,那就特別感謝大家呢!
雖然大多數(shù)技術(shù)平臺發(fā)這個水滴籌,有些人會表示不理解,有的甚至說會影響社區(qū)氛圍。我覺得這種擔心很正常,但是有點把問題放大了,首先這個是一個特別小概率的事件,并不會存在說大家都這樣做就造成不好的影響。其次有人還說,會過渡消費社會這種同情和愛心,這種擔心挺好,但是人總是會有分辨是非的能力,如果能夠幫忙那就盡綿薄之力,如果不能幫忙那也不要亂扣帽子。
我知道最近世麟心情是錯綜復(fù)雜,但還好的是絕大多數(shù)程序員都是特別有善心的。我始終覺得一個能夠堅持寫技術(shù)博客,而且還寫了這么多,掘金還是以前的掘金,沒有發(fā)生變化。
程序員爸爸癱瘓14年,媽媽又這樣,幫幫南塵!
01.先看一個需求分析案例
案例說明
加載一個本地的大圖片或者網(wǎng)絡(luò)圖片,從加載到設(shè)置到View上,如何減下內(nèi)存,避免加載圖片OOM。
案例分析
在展示高分辨率圖片的時候,最好先將圖片進行壓縮。壓縮后的圖片大小應(yīng)該和用來展示它的控件大小相近,在一個很小的ImageView上顯示一張超大的圖片不會帶來任何視覺上的好處,但卻會占用相當多寶貴的內(nèi)存,而且在性能上還可能會帶來負面影響。
02.Bitmap占用內(nèi)存介紹
網(wǎng)絡(luò)圖片計算Bitmap的內(nèi)存大小
bitmap內(nèi)存大小 = 圖片長度 x 圖片寬度 x 單位像素占用的字節(jié)數(shù)
起決定因素就是最后那個參數(shù)了,Bitmap"常見有2種編碼方式:ARGB_8888和RGB_565,ARGB_8888每個像素點4個byte,RGB_565是2個byte,一般都采用ARGB_8888這種。那么常見的1080*1920的圖片內(nèi)存占用就是:1920 x 1080 x 4 = 7.9M
加載本地資源計算Bitmap的內(nèi)存大小
加載一張本地資源圖片,那么它占用的內(nèi)存 = width height nTargetDensity/inDensity 一個像素所占的內(nèi)存。
詳細可以看這篇文章04.Bitmap計算內(nèi)存
正確說法,這個注意呢?計算公式如下所示
對資源文件:width height nTargetDensity/inDensity nTargetDensity/inDensity 一個像素所占的內(nèi)存;
別的:width height 一個像素所占的內(nèi)存;
03.影響B(tài)itmap占用內(nèi)存因素
影響B(tài)itmap占用內(nèi)存的因素:
圖片最終加載的分辨率;
圖片的格式(PNG/JPEG/BMP/WebP);
圖片所存放的drawable目錄;
圖片屬性設(shè)置的色彩模式;
設(shè)備的屏幕密度;
04.圖像加載的方式
獲取圖像的來源一般有三種源頭:
1.從網(wǎng)絡(luò)加載2.從文件讀取3.從資源文件加載
針對這三種情況我們一般使用BitmapFactory的
decodeStream,decodeFile,decodeResource,這三個函數(shù)來獲取到bitmap然后再調(diào)用ImageView的setImageBitmap函數(shù)進行展現(xiàn)。
05.加載圖像內(nèi)存去哪里了
思考一下:內(nèi)存去哪里了(為什么被消耗了這么多)?
其實我們的內(nèi)存就是去bitmap里了,BitmapFactory的每個decode函數(shù)都會生成一個bitmap對象,用于存放解碼后的圖像,然后返回該引用。如果圖像數(shù)據(jù)較大就會造成bitmap對象申請的內(nèi)存較多,如果圖像過多就會造成內(nèi)存不夠用自然就會出現(xiàn)out of memory的現(xiàn)象。
為何容易OOM?
通過BitmapFactory的decode的這些方法會嘗試為已經(jīng)構(gòu)建的bitmap分配內(nèi)存,這時就會很容易導致OOM出現(xiàn)。為此每一種解析方法都提供了一個可選的BitmapFactory.Options參數(shù),將這個參數(shù)的inJustDecodeBounds屬性設(shè)置為true就可以讓解析方法禁止為bitmap分配內(nèi)存,返回值也不再是一個Bitmap對象,而是null。
06.具體實現(xiàn)加載圖片步驟為了避免OOM異常,最好在解析每張圖片的時候都先檢查一下圖片的大小,除非你非常信任圖片的來源,保證這些圖片都不會超出你程序的可用內(nèi)存。
現(xiàn)在圖片的大小已經(jīng)知道了,我們就可以決定是把整張圖片加載到內(nèi)存中還是加載一個壓縮版的圖片到內(nèi)存中。以下幾個因素是我們需要考慮的:
預(yù)估一下加載整張圖片所需占用的內(nèi)存。
為了加載這一張圖片你所愿意提供多少內(nèi)存。
用于展示這張圖片的控件的實際大小。
當前設(shè)備的屏幕尺寸和分辨率。
比如,你的ImageView只有128x96像素的大小,只是為了顯示一張縮略圖,這時候把一張2048x1536像素的圖片完全加載到內(nèi)存中顯然是不值得的。
6.1 對圖片進行壓縮
怎樣才能對圖片進行壓縮呢?
通過設(shè)置BitmapFactory.Options中inSampleSize的值就可以實現(xiàn)。
比如我們有一張2048x1536像素的圖片,將inSampleSize的值設(shè)置為4,就可以把這張圖片壓縮成512x384像素。
原本加載這張圖片需要占用13M的內(nèi)存,壓縮后就只需要占用0.75M了(假設(shè)圖片是ARGB_8888類型,即每個像素點占用4個字節(jié))。
下面的方法可以根據(jù)傳入的寬和高,計算出合適的inSampleSize值:
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // 源圖片的高度和寬度 final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { // 計算出實際寬高和目標寬高的比率 final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); // 選擇寬和高中最小的比率作為inSampleSize的值,這樣可以保證最終圖片的寬和高 // 一定都會大于等于目標的寬和高。 inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; }6.2 設(shè)置BitmapFactory.Options屬性
大概步驟如下所示
要將BitmapFactory.Options的inJustDecodeBounds屬性設(shè)置為true,解析一次圖片。注意這個地方是核心,這個解析圖片并沒有生成bitmap對象(也就是說沒有為它分配內(nèi)存控件),而僅僅是拿到它的寬高等屬性。
然后將BitmapFactory.Options連同期望的寬度和高度一起傳遞到到calculateInSampleSize方法中,就可以得到合適的inSampleSize值了。這一步會壓縮圖片。
之后再解析一次圖片,使用新獲取到的inSampleSize值,并把inJustDecodeBounds設(shè)置為false,就可以得到壓縮后的圖片了。此時才正式創(chuàng)建了bitmap對象,由于前面已經(jīng)對它壓縮了,所以你會發(fā)現(xiàn)此時所占內(nèi)存大小已經(jīng)很少了。
具體的實現(xiàn)代碼
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // 第一次解析將inJustDecodeBounds設(shè)置為true,來獲取圖片大小 final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // 調(diào)用上面定義的方法計算inSampleSize值 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // 使用獲取到的inSampleSize值再次解析圖片 options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); }
思考:inJustDecodeBounds這個參數(shù)是干什么的?
如果設(shè)置為true則表示decode函數(shù)不會生成bitmap對象,僅是將圖像相關(guān)的參數(shù)填充到option對象里,這樣我們就可以在不生成bitmap而獲取到圖像的相關(guān)參數(shù)了。
為何設(shè)置兩次inJustDecodeBounds屬性?
第一次:設(shè)置為true則表示decode函數(shù)不會生成bitmap對象,僅是將圖像相關(guān)的參數(shù)填充到option對象里,這樣我們就可以在不生成bitmap而獲取到圖像的相關(guān)參數(shù)。
第二次:將inJustDecodeBounds設(shè)置為false再次調(diào)用decode函數(shù)時就能生成bitmap了。而此時的bitmap已經(jīng)壓縮減小很多了,所以加載到內(nèi)存中并不會導致OOM。
6.3 設(shè)置bitmap到View上
將任意一張圖片壓縮成100*100的縮略圖,并在ImageView上展示。
mImageView.setImageBitmap( decodeSampledBitmapFromResource(getResources(), R.id.ycimage, 100, 100));其他介紹 01.關(guān)于博客匯總鏈接
1.技術(shù)博客匯總
2.開源項目匯總
3.生活博客匯總
4.喜馬拉雅音頻匯總
5.其他匯總
02.關(guān)于我的博客github:https://github.com/yangchong211
知乎:https://www.zhihu.com/people/...
簡書:http://www.jianshu.com/u/b7b2...
csdn:http://my.csdn.net/m0_37700275
喜馬拉雅聽書:http://www.ximalaya.com/zhubo...
開源中國:https://my.oschina.net/zbj161...
泡在網(wǎng)上的日子:http://www.jcodecraeer.com/me...
阿里云博客:https://yq.aliyun.com/users/a... 239.headeruserinfo.3.dT4bcV
segmentfault頭條:https://segmentfault.com/u/xi...
掘金:https://juejin.im/user/593943...
項目案例:https://github.com/yangchong2...文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/75334.html
摘要:導語智能手機發(fā)展到今天已經(jīng)有十幾個年頭,手機的軟硬件都已經(jīng)發(fā)生了翻天覆地的變化,特別是陣營,從一開始的一兩百到今天動輒,內(nèi)存。恰好最近做了內(nèi)存優(yōu)化相關(guān)的工作,這里也對內(nèi)存優(yōu)化相關(guān)的知識做下總結(jié)。 導語 智能手機發(fā)展到今天已經(jīng)有十幾個年頭,手機的軟硬件都已經(jīng)發(fā)生了翻天覆地的變化,特別是Android陣營,從一開始的一兩百M到今天動輒4G,6G內(nèi)存。然而大部分的開發(fā)者觀看下自己的異常上報系...
摘要:另一種方式就是是一個簡單的,方便的內(nèi)存檢測工具,可以輕易的發(fā)現(xiàn)內(nèi)存問題,還會生成更加簡單清晰的報告。是一個開源的檢測內(nèi)存泄露的庫。 在開發(fā)Android應(yīng)用的過程中如果需要處理圖片或者大量數(shù)據(jù)的時候,就有可能會遇到OOM(java.lang.OutOfMemoryError),一般出現(xiàn)最多的是在創(chuàng)建Bitmap上,也有可能是在內(nèi)存中處理了大量的數(shù)據(jù)上。出現(xiàn)OOM應(yīng)用會直接崩潰,即使沒有...
閱讀 3680·2021-10-09 09:58
閱讀 1231·2021-09-22 15:20
閱讀 2520·2019-08-30 15:54
閱讀 3540·2019-08-30 14:08
閱讀 915·2019-08-30 13:06
閱讀 1850·2019-08-26 12:16
閱讀 2709·2019-08-26 12:11
閱讀 2535·2019-08-26 10:38