Android內(nèi)存優(yōu)化五:Bitmap優(yōu)化

Android內(nèi)存優(yōu)化一:java垃圾回收機制
Android內(nèi)存優(yōu)化二:內(nèi)存泄漏
Android內(nèi)存優(yōu)化三:內(nèi)存泄漏檢測與監(jiān)控
Android內(nèi)存優(yōu)化四:OOM
Android內(nèi)存優(yōu)化五:Bitmap優(yōu)化

一、占用內(nèi)存計算

1.從本地加載或者從網(wǎng)絡加載

// 1個字節(jié)8位
內(nèi)存占用 = 圖片寬 * 高 * 一個像素點占用的字節(jié)數(shù)

2.從資源目錄記載数冬, 圖片會被壓縮

壓縮比:scale = (flaot) targetDensity / density

targetDensity : 設備屏幕像素密度dpi

density: 圖片對應的文件夾的像素密度dpi

image

1)帽撑、同一張圖片放在不同的資源目錄下,其分辨率會有變化。

2)甥温、Bitmap的分辨率越高调鬓,其解析后的寬高越小,甚至小于原有的圖片(及縮放)耸成,從而內(nèi)存也響應的減少。

3)浴鸿、圖片不放置任何資源目錄時井氢,其使用默認分辨率mdpi:160。

4)赚楚、資源目錄分辨率和屏幕分辨率一致時毙沾,圖片尺寸不會縮放。

Bitmap放在資源目錄中的計算方式為:

內(nèi)存占用 = 像素數(shù)據(jù)總大小 = 圖片寬 * 圖片高 * scale ^ 2 * 一個像素點占用的字節(jié)數(shù)

二宠页、圖片內(nèi)存優(yōu)化

主要通過編碼左胞、采樣、復用举户、匿名共享區(qū)進行優(yōu)化

編碼

由于ARGB_4444的畫質(zhì)慘不忍睹烤宙,一般假如對圖片沒有透明度要求的話,可以改成RGB_565俭嘁,相比ARGB_8888將節(jié)省一半的內(nèi)存開銷

image

其中躺枕,A代表透明度;R代表紅色;G代表綠色拐云;B代表藍色罢猪。

ALPHA_8 表示8位Alpha位圖,即A=8,一個像素點占用1個字節(jié),它沒有顏色,只有透明度。

ARGB_4444 表示16位ARGB位圖叉瘩,即A=4,R=4,G=4,B=4,一個像素點占4+4+4+4=16位膳帕,2個字節(jié)。

ARGB_8888 表示32位ARGB位圖薇缅,即A=8,R=8,G=8,B=8,一個像素點占8+8+8+8=32位危彩,4個字節(jié)。

RGB_565 表示16位RGB位圖,即R=5,G=6,B=5,它沒有透明度,一個像素點占5+6+5=16位泳桦,2個字節(jié)汤徽。

采樣

bitmap的占用內(nèi)存,是以bitmap的寬高和每個像素占用的字節(jié)數(shù)決定的灸撰。

BitmapFactory.Options options = new BitmapFactory.Options();
//不獲取圖片谒府,不加載到內(nèi)存中,只返回圖片屬性
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(photoPath, options);
//圖片的寬高
int outHeight = options.outHeight;
int outWidth = options.outWidth;
Log.d("bitmap", "圖片寬=" + outWidth + "圖片高=" + outHeight);
//計算采樣率
int i = utils.computeSampleSize(options, -1, 1000 * 1000);
//設置采樣率梧奢,不能小于1 假如是2 則寬為之前的1/2狱掂,高為之前的1/2演痒,一共縮小1/4 以此類推
options.inSampleSize = i;
Log.d("bitmap", "采樣率為=" + i);
//圖片格式壓縮
//options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(photoPath, options);
float bitmapsize = getBitmapsize(bitmap);
Log.d("bitmap","壓縮后:圖片占內(nèi)存大小" + bitmapsize + "MB / 寬度=" + bitmap.getWidth() + "高度=" + bitmap.getHeight());

// 打印
bitmap: 原圖:圖片占內(nèi)存大小=45.776367MB / 寬度=4000高度=3000
bitmap: 圖片寬=4000圖片高=3000
bitmap: 采樣率為=4
bitmap: 壓縮后:圖片占內(nèi)存大小1.4296875MB / 寬度=1000高度=750

根據(jù)BitmapFactory 的采樣率進行壓縮 設置采樣率亲轨,不能小于1 假如是2 則寬為之前的1/2,高為之前的1/2鸟顺,一共縮小1/4 以此類推

復用

圖片復用指的是inBitmap這個屬性惦蚊。

不使用這個屬性,你加載三張圖片讯嫂,系統(tǒng)會給你分配三份內(nèi)存空間蹦锋,用于分別儲存這三張圖片

如果用了inBitmap這個屬性,加載三張圖片欧芽,這三張圖片會指向同一塊內(nèi)存莉掂,而不用開辟三塊內(nèi)存空間。

inBitmap的限制:

1千扔、3.0-4.3

復用的圖片大小必須相同

編碼必須相同

2憎妙、4.4以上

復用的空間大于等于即可

編碼不必相同

3、不支持WebP

4曲楚、圖片復用厘唾,這個屬性必須設置為true;

options.inMutable = true;

匿名共享內(nèi)存

Android 系統(tǒng)為了進程間共享數(shù)據(jù)開辟的一塊內(nèi)存區(qū)域龙誊,由于這塊區(qū)域不受應用的Head的大小限制抚垃,相當于可以繞開oom,F(xiàn)aceBook的Fresco首次應用到實際中。

限制:5.0以后就限制了匿名共享內(nèi)存的使用鹤树。

Android的內(nèi)存區(qū)域

  1. Java Heap(Dalvik Heap)铣焊,這部分的內(nèi)存區(qū)域是由Dalvik虛擬機管理,通過Java中 new 關鍵字來申請一塊新內(nèi)存罕伯。這塊區(qū)域的內(nèi)存是由GC直接管理粗截,能夠自動回收內(nèi)存。這塊內(nèi)存的大小會受到系統(tǒng)限制捣炬,當內(nèi)存超過APP最大可用內(nèi)存時會OOM

  2. Native Heap熊昌,這部分內(nèi)存區(qū)域是在C++中申請的,它不受限于APP的最大可用內(nèi)存限制湿酸,而只是受限于設備的物理可用內(nèi)存限制婿屹。它的缺點在于沒有自動回收機制,只能通過C++語法來釋放申請的內(nèi)存

  3. Ashmem(Android匿名共享內(nèi)存)推溃,這部分內(nèi)存類似于Native內(nèi)存區(qū)昂利,但是它是受Android系統(tǒng)底層管理的,當Android系統(tǒng)內(nèi)存不足時铁坎,會回收Ashmem區(qū)域中狀態(tài)是 unpin 的對象內(nèi)存塊蜂奸,如果不希望對象被回收,可以通過 pin 來保護一個對象

使用 inBitmap 需要注意幾個限制條件

在SDK 11 -> 18之間硬萍,重用的bitmap大小必須是一致的扩所,例如給inBitmap賦值的圖片大小為100-100,那么新申請的bitmap必須也為100-100才能夠被重用朴乖。從SDK 19開始祖屏,新申請的bitmap大小必須小于或者等于已經(jīng)賦值過的bitmap大小。 新申請的bitmap與舊的bitmap必須有相同的解碼格式买羞,例如大家都是8888的袁勺,如果前面的bitmap是8888,那么就不能支持4444與565格式的bitmap了畜普。 我們可以創(chuàng)建一個包含多種典型可重用bitmap的對象池期丰,這樣后續(xù)的bitmap創(chuàng)建都能夠找到合適的“模板”去進行重用。

圖片到底儲存在哪里

image

8.0Bitmap的像素數(shù)據(jù)存儲在Native吃挑,為什么又改為Native存儲呢钝荡?

因為8.0共享了整個系統(tǒng)的內(nèi)存,測試8.0手機如果一直創(chuàng)建Bitmap儒鹿,如果手機內(nèi)存有1G化撕,那么你的應用加載1G也不會oom。

LRU管理Bitmap

可以利用LRU開管理Bitmap约炎,給他設置內(nèi)存最大值植阴,及時回收蟹瘾。

圖片壓縮

  1. 采樣壓縮(設置采樣率,不能小于1 假如是2 則寬為之前的1/2掠手,高為之前的1/2憾朴,一共縮小1/4 以此類推)
  2. 質(zhì)量壓縮
// 這個壓縮是保持像素的前提下改變圖片的位深及透明度,來達到壓縮的目的喷鸽,
// 不過這種壓縮不會改變圖片在內(nèi)存中的大小众雷,而且這種壓縮會導致圖片的失真,
// 但是有沒有壓縮到100k左右做祝,還不失真的方法砾省?
bitmap.compress(Bitmap.CompressFormat.JPEG, 20, 
new FileOutputStream("sdcard/result.jpg"));

加載高清圖

BitmapRegionDecoder

//支持傳入圖片的路徑,流和圖片修飾符等
BitmapRegionDecoder mDecoder = BitmapRegionDecoder.newInstance(path, false);
//需要顯示的區(qū)域就有由rect控制混槐,options來控制圖片的屬性
Bitmap bitmap = mDecoder.decodeRegion(mRect, options);
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末编兄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子声登,更是在濱河造成了極大的恐慌狠鸳,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悯嗓,死亡現(xiàn)場離奇詭異件舵,居然都是意外死亡,警方通過查閱死者的電腦和手機脯厨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門铅祸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人俄认,你說我怎么就攤上這事个少。” “怎么了眯杏?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長壳澳。 經(jīng)常有香客問我岂贩,道長,這世上最難降的妖魔是什么巷波? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任萎津,我火速辦了婚禮,結果婚禮上抹镊,老公的妹妹穿的比我還像新娘锉屈。我一直安慰自己,他們只是感情好垮耳,可當我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布颈渊。 她就那樣靜靜地躺著遂黍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪俊嗽。 梳的紋絲不亂的頭發(fā)上雾家,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機與錄音绍豁,去河邊找鬼芯咧。 笑死,一個胖子當著我的面吹牛竹揍,可吹牛的內(nèi)容都是我干的敬飒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼芬位,長吁一口氣:“原來是場噩夢啊……” “哼驶拱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起晶衷,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蓝纲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后晌纫,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體税迷,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年锹漱,在試婚紗的時候發(fā)現(xiàn)自己被綠了箭养。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡哥牍,死狀恐怖毕泌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嗅辣,我是刑警寧澤撼泛,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站澡谭,受9級特大地震影響愿题,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蛙奖,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一潘酗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧雁仲,春花似錦仔夺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽日裙。三九已至,卻和暖如春灶体,著一層夾襖步出監(jiān)牢的瞬間阅签,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工蝎抽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留政钟,地道東北人。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓樟结,卻偏偏與公主長得像养交,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子瓢宦,可洞房花燭夜當晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 優(yōu)化目錄 優(yōu)化的意義 減少 OOM碎连,提高應用穩(wěn)定性。 減少卡頓驮履,提高應用流暢度鱼辙。 減少內(nèi)存占用,提...
    三流之路閱讀 1,333評論 0 1
  • 圖片加載 在客戶端開發(fā)中玫镐,圖片加載和顯示倒戏,是非常常見的功能了。常見的圖片獲取途徑有網(wǎng)絡傳輸恐似,本地文件獲取和資源加載...
    zackyG閱讀 1,907評論 1 2
  • 大家都知道杜跷,我們編寫的應用程序的內(nèi)存是有限的,程序內(nèi)存占用過高很容易導致OOM異常矫夷。我們可以通過下面的代碼看出每個...
    _Rice_閱讀 440評論 0 2
  • 為什么圖片的三級緩存葛闷,內(nèi)存是第一位 硬件快:內(nèi)存本身讀取、存入速度快 復用快:解碼成果有效保存双藕,復用時淑趾,直接使用解...
    今陽說閱讀 3,129評論 0 17
  • Android開發(fā)中,Bitmap是經(jīng)常會遇到的對象蔓彩,特別是在列表圖片展示治笨、大圖顯示等界面。而Bitmap實實在在...
    Dragon_Boat閱讀 21,806評論 17 68