国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 系統(tǒng) > Android > 正文

在Android中高效的加載大圖的方法示例

2019-12-12 00:48:57
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

將大圖加載到內(nèi)存中總是令人痛苦,因?yàn)槲覀兘?jīng)常會(huì)在應(yīng)用的崩潰報(bào)告中看到OOM(Out Of Memory)的bug。大家都知道,Android系統(tǒng)的內(nèi)存有限。我們必須牢記這一點(diǎn)。

stackoverflow上有很多關(guān)于大圖加載的問(wèn)題,當(dāng)你的應(yīng)用程序遇到OOM的時(shí)候,你可以選擇直接復(fù)制粘貼其中的答案來(lái)解決這個(gè)問(wèn)題。因此,你完全可以略過(guò)本篇文章,但我想介紹一些加載大圖的基礎(chǔ)知識(shí)及其實(shí)際工作的原理。

我只想解釋圖片解碼背后的邏輯。我建議你使用Picasso或Glide來(lái)加載圖片。沒(méi)有必要重新發(fā)明輪子。

將圖片加載到內(nèi)存中

這很簡(jiǎn)單。你只需要使用BitmapFactory來(lái)解碼你的圖片。

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.hqimage);imageView.setImageBitmap(bitmap);

看起來(lái)一切正常。但是我要告訴你一個(gè)問(wèn)題,讓我們看看這張解碼過(guò)的圖片在內(nèi)存中實(shí)際占據(jù)的空間大小。

bitmap.getByteCount()方法將返回bitmap的大小。 這張圖片在內(nèi)存中的大小為12262248字節(jié),相當(dāng)于12.3 MB。是的,你可能會(huì)感到困惑。因?yàn)檫@張圖片在磁盤(pán)上的實(shí)際大小約為3.5 MB,而getByteCount()方法返回的值遠(yuǎn)大于它。原因如下:

存儲(chǔ)在磁盤(pán)上的圖片是被壓縮過(guò)的(以JPG,PNG或類(lèi)似的格式存儲(chǔ))。 一旦將圖片加載到內(nèi)存中,它就不再被壓縮,并占用盡可能多的圖片的所有像素所需的內(nèi)存空間。

加載大圖的步驟

  1. 獲取圖片的寬和高
  2. 根據(jù)圖片的寬和高計(jì)算縮放比
  3. 使用壓縮比將圖片加載到內(nèi)存中。

BitmapFactory.Options

BitmapFactory可以為我們提供圖片的元數(shù)據(jù)。我們可以使用這個(gè)類(lèi)來(lái)實(shí)現(xiàn)第一步。

BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeResource(getResources(), R.mipmap.hqimage, options);

我們將BitmapFactory.Options實(shí)例傳遞給BitmapFactory.decodeSource()方法。 options.inJustDecodeBounds = true 是什么意思?這句代碼是指我們不想將圖片加載到內(nèi)存中。我們只想獲取圖片的相關(guān)信息(寬度,高度等),并使用這些信息來(lái)計(jì)算縮放比例。

我們運(yùn)行這段代碼和并打印圖片的信息:

options.outHeight : 1126
options.outWidth : 2000
options.bitmap : null

它只輸出了圖片的高度和寬度。

Reducing Image Size (In Memory)

現(xiàn)在我們需要計(jì)算 inSampleSize 。什么是inSampleSize? inSampleSize是BitmapFactory.Options類(lèi)的一個(gè)屬性,用于設(shè)置圖片的縮放比。

如果我們有一張尺寸為1000x1000的圖片,并且在解碼之前設(shè)置inSampleSize的值為2, 那么解碼之后,我們將得到一張尺寸為500x500的圖片。 如果我們有一張尺寸為200x400的圖片,并且在解碼之前設(shè)置inSampleSize的值為5, 那么解碼之后,我們將得到一張尺寸為40x80的圖片。

BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;options.inSampleSize = 3; BitmapFactory.decodeResource(getResources(), R.mipmap.hqimage, options);

我們可以直接這樣做嗎?不能,因?yàn)槲覀儾恢缊D片大小是多少。如果它是小圖片,并且我們使其更小,那么我們的用戶可以看到的就是一些像素而不是圖像。有一些圖片需要縮放5倍,另一些圖片則需要縮放2倍。我們不能將縮放比設(shè)置為一個(gè)常數(shù),所以我們必須根據(jù)圖片的大小來(lái)計(jì)算它的值。

如何計(jì)算inSampleSize的值取決于您。我的意思是,你可以根據(jù)你的需要編寫(xiě)inSampleSize的計(jì)算方法。在android官方文檔中,計(jì)算結(jié)果是2的冪次方。

options.inSampleSize = calculateInSampleSize(options, 500,500);options.inJustDecodeBounds = false;Bitmap smallBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.hqimage, options);

這里我們將 inJustDecodeBounds 的值設(shè)為false,并獲得了一個(gè)bitmap對(duì)象。現(xiàn)在,bitmap.getByteCount()方法返回的圖片大小是3.1 MB。這是它在內(nèi)存中的大小。正如我之前說(shuō)過(guò)的,圖片存儲(chǔ)在磁盤(pán)上時(shí)會(huì)被壓縮。當(dāng)我們將它們加載到內(nèi)存中時(shí)它們會(huì)占據(jù)更大的內(nèi)存空間。通過(guò)上面這種方法,我們將它在內(nèi)存中占據(jù)的空間大小從12.3 MB減少到了3.1 MB,減少了75%。

Reducing Image Size (In Disk)

我們還可以使用Bitmap的 compress 方法對(duì)磁盤(pán)上的圖片進(jìn)行壓縮。

我們來(lái)看看在不改變圖片質(zhì)量的情況下圖片被壓縮后的大小。 100 表示與原圖保持相同的質(zhì)量。

ByteArrayOutputStream bos = new ByteArrayOutputStream();bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);byte[] bitmapdata = bos.toByteArray();

通過(guò)計(jì)算得到圖片在磁盤(pán)上的大小為1.6 MB。

我們把compress方法中的質(zhì)量參數(shù)改為50,并再次計(jì)算圖片大小。

bitmap.compress(Bitmap.CompressFormat.JPEG, 50, bos);

通過(guò)計(jì)算得到圖片在磁盤(pán)上的大小為24.4 KB。

注意:在改變compress方法中的質(zhì)量參數(shù)的時(shí)候,壓縮格式應(yīng)該是.JPEG。設(shè)置為PNG格式的時(shí)候,修改是無(wú)效的。

下面是一張對(duì)比效果圖:


以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 咸宁市| 巴楚县| 土默特左旗| 布尔津县| 平原县| 齐河县| 四平市| 太康县| 四平市| 炉霍县| 平阴县| 华蓥市| 任丘市| 宝山区| 湖北省| 南汇区| 彩票| 潞城市| 清原| 云南省| 新建县| 黔东| 镇赉县| 枣庄市| 临汾市| 嘉祥县| 朝阳区| 邵东县| 赞皇县| 滕州市| 德化县| 南召县| 石城县| 潞城市| 类乌齐县| 景洪市| 沂源县| 威信县| 响水县| 麻栗坡县| 新源县|