Android處理大圖避免OOM的完整方案
1. 計(jì)算合適的縮放比例
使用 BitmapFactory.Options 的 inSampleSize 對(duì)圖片進(jìn)行采樣壓縮:
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int width = options.outWidth;
final int height = options.outHeight;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfWidth = width / 2;
final int halfHeight = height / 2;
while ((halfWidth / inSampleSize) >= reqWidth
&& (halfHeight / inSampleSize) >= reqHeight) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
2. 分步加載圖片
- 步驟 1:僅讀取圖片尺寸(不分配內(nèi)存)
BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(getResources(), R.drawable.large_image, options); int imageWidth = options.outWidth; int imageHeight = options.outHeight;
- 步驟 2:動(dòng)態(tài)計(jì)算縮放比例并加載
options.inJustDecodeBounds = false; options.inSampleSize = calculateInSampleSize(options, targetWidth, targetHeight); Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.large_image, options);
3. 優(yōu)化內(nèi)存配置
使用更低的像素格式(如不需要透明度):
options.inPreferredConfig = Bitmap.Config.RGB_565; // 每個(gè)像素占 2 字節(jié)(內(nèi)存減半)
禁用自動(dòng)縮放(避免系統(tǒng)根據(jù)屏幕密度調(diào)整大?。?/p>
options.inScaled = false;
4. 按需加載局部區(qū)域(超大圖場(chǎng)景)
使用 BitmapRegionDecoder 分塊加載:
InputStream is = getAssets().open("large_image.jpg");
BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
Rect rect = new Rect(startX, startY, startX + width, startY + height);
Bitmap bitmap = decoder.decodeRegion(rect, options);
5. 及時(shí)回收資源
在 onDestroy() 或不再需要 Bitmap 時(shí)主動(dòng)回收:
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
bitmap = null;
}
避免在 onDraw() 中頻繁創(chuàng)建 Bitmap(利用緩存或復(fù)用機(jī)制)。
6. 使用第三方庫(kù)(推薦)
Glide:自動(dòng)處理圖片縮放、內(nèi)存/磁盤緩存、生命周期管理。
Glide.with(context)
.load("path/to/image")
.override(targetWidth, targetHeight)
.into(imageView);
Picasso:類似 Glide,提供簡(jiǎn)潔的 API 管理大圖。
7. 配置大堆或硬件加速
在 AndroidManifest.xml 中為 Activity 添加 largeHeap="true"(臨時(shí)緩解,不推薦長(zhǎng)期依賴):
<application android:largeHeap="true">
啟用硬件加速(在部分場(chǎng)景下減少內(nèi)存壓力):
<activity android:hardwareAccelerated="true" />
關(guān)鍵公式:內(nèi)存估算
內(nèi)存占用 = 圖片寬度 * 圖片高度 * 每像素字節(jié)數(shù) 例如:4000x3000 的 ARGB_8888 圖片 = 4000 * 3000 * 4B ≈ 48MB
通過(guò)上述策略,可顯著降低內(nèi)存占用,有效避免 OOM。實(shí)際開(kāi)發(fā)中優(yōu)先使用 Glide/Picasso 等成熟庫(kù),減少手動(dòng)處理風(fēng)險(xiǎn)。
以上就是Android處理大圖避免OOM的完整方案的詳細(xì)內(nèi)容,更多關(guān)于Android處理大圖避免OOM的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android開(kāi)發(fā)中Google為什么不讓用Handler的runWithScissors()
這篇文章主要介紹了Android開(kāi)發(fā)中Google為什么不讓用Handler的runWithScissors(),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
Android使用自定義alertdialog實(shí)現(xiàn)確認(rèn)退出按鈕
本文通過(guò)實(shí)例代碼給大家詳解Android使用自定義alertdialog實(shí)現(xiàn)確認(rèn)退出按鈕,對(duì)alertdialog退出按鈕相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧2016-01-01
Android開(kāi)發(fā)Jetpack組件Room用例講解
這篇文章主要為大家介紹了Android?Jetpack組件Room的使用案例的詳細(xì)講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02
Android自定義方框EditText注冊(cè)驗(yàn)證碼
這篇文章主要為大家詳細(xì)介紹了Android自定義方框EditText注冊(cè)驗(yàn)證碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06
Android中關(guān)于FragmentA嵌套FragmentB的問(wèn)題
這篇文章主要為大家詳細(xì)介紹了Android中關(guān)于FragmentA嵌套FragmentB的問(wèn)題,感興趣的小伙伴們可以參考一下2016-08-08
Android Studio使用教程(六):Gradle多渠道打包
這篇文章主要介紹了Android Studio使用教程(六):Gradle多渠道打包,本文講解了友盟多渠道打包、assemble結(jié)合Build Variants來(lái)創(chuàng)建task、完整的gradle腳本等內(nèi)容,需要的朋友可以參考下2015-05-05
Android 應(yīng)用的全屏和非全屏實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 應(yīng)用的全屏和非全屏實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2017-05-05
Android利用Hero實(shí)現(xiàn)列表與詳情頁(yè)無(wú)縫切換動(dòng)畫
本文我們將利用Hero動(dòng)畫實(shí)現(xiàn)一個(gè)簡(jiǎn)單案例:實(shí)現(xiàn)列表與詳情頁(yè)無(wú)縫切換動(dòng)畫,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以動(dòng)手嘗試一下2022-06-06
Android開(kāi)發(fā)之無(wú)痕過(guò)渡下拉刷新控件的實(shí)現(xiàn)思路詳解
下拉刷新效果功能在程序開(kāi)發(fā)中經(jīng)常會(huì)見(jiàn)到,今天小編抽時(shí)間給大家分享Android開(kāi)發(fā)之無(wú)痕過(guò)渡下拉刷新控件的實(shí)現(xiàn)思路詳解,需要的朋友參考下吧2016-11-11

