最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Bitmap引起的OOM問(wèn)題

 更新時(shí)間:2023年04月28日 08:41:47   作者:向陽(yáng)逐夢(mèng)  
這篇文章主要介紹了Bitmap引起的OOM問(wèn)題,為什么會(huì)引起,以及避免引起的方法,文中有詳細(xì)的代碼示例,有需要的朋友可以參考下

1.什么是OOM?為什么會(huì)引起OOM?

答:Out Of Memory(內(nèi)存溢出),我們都知道Android系統(tǒng)會(huì)為每個(gè)APP分配一個(gè)獨(dú)立的工作空間,或者說(shuō)分配一個(gè)單獨(dú)的Dalvik虛擬機(jī),這樣每個(gè)APP都可以獨(dú)立運(yùn)行而不相互影響!而Android對(duì)于每個(gè)Dalvik虛擬機(jī)都會(huì)有一個(gè)最大內(nèi)存限制,如果當(dāng)前占用的內(nèi)存加上我們申請(qǐng)的內(nèi)存資源超過(guò)了這個(gè)限制,系統(tǒng)就會(huì)拋出OOM錯(cuò)誤!另外,這里別和RAM混淆了,即時(shí)當(dāng)前RAM中剩余的內(nèi)存有1G多,但是OOM還是會(huì)發(fā)生!別把RAM(物理內(nèi)存)和OOM扯到一起!另外RAM不足的話(huà),就是殺應(yīng)用了,而不是僅僅是OOM了!而這個(gè)Dalvik中的最大內(nèi)存標(biāo)準(zhǔn),不同的機(jī)型是不一樣的,可以調(diào)用:

ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
Log.e("HEHE","最大內(nèi)存:" + activityManager.getMemoryClass());

獲得正常的最大內(nèi)存標(biāo)準(zhǔn),又或者直接在命令行鍵入:

adb shell getprop | grep dalvik.vm.heapgrowthlimit

你也可以打開(kāi)系統(tǒng)源碼/system/build.prop文件,看下文件中這一部分的信息得出:

dalvik.vm.heapstartsize=8m
dalvik.vm.heapgrowthlimit=192m
dalvik.vm.heapsize=512m
dalvik.vm.heaptargetutilization=0.75
dalvik.vm.heapminfree=2m
dalvik.vm.heapmaxfree=8m

你也可以試試自己手頭的機(jī)子~

好啦,不扯了,關(guān)于OOM問(wèn)題的產(chǎn)生,就扯到這里,再扯就到內(nèi)存管理那一塊了,可是個(gè)大塊頭,現(xiàn)在還啃不動(dòng)...下面我們來(lái)看下避免Bitmap OOM的一些技巧吧!

2.避免Bitmap引起的OOM技巧小結(jié)

1)采用低內(nèi)存占用量的編碼方式

上一節(jié)說(shuō)了BitmapFactory.Options這個(gè)類(lèi),我們可以設(shè)置下其中的inPreferredConfig屬性,默認(rèn)是Bitmap.Config.ARGB_8888,我們可以修改成Bitmap.Config.ARGB_4444Bitmap.Config ARGB_4444:每個(gè)像素占四位,即A=4,R=4,G=4,B=4,那么一個(gè)像素點(diǎn)占4+4+4+4=16位Bitmap.Config ARGB_8888:每個(gè)像素占八位,即A=8,R=8,G=8,B=8,那么一個(gè)像素點(diǎn)占8+8+8+8=32位默認(rèn)使用ARGB_8888,即一個(gè)像素占4個(gè)字節(jié)!

2)圖片壓縮

同樣是BitmapFactory.Options,我們通過(guò)inSampleSize設(shè)置縮放倍數(shù),比如寫(xiě)2,即長(zhǎng)寬變?yōu)樵瓉?lái)的1/2,圖片就是原來(lái)的1/4,如果不進(jìn)行縮放的話(huà)設(shè)置為1即可!但是不能一味的壓縮,畢竟這個(gè)值太小的話(huà),圖片會(huì)很模糊,而且要避免圖片的拉伸變形,所以需要我們?cè)诔绦蛑袆?dòng)態(tài)的計(jì)算,這個(gè)inSampleSize的合適值,而Options中又有這樣一個(gè)方法:inJustDecodeBounds,將該參數(shù)設(shè)置為true后,decodeFiel并不會(huì)分配內(nèi)存空間,但是可以計(jì)算出原始圖片的長(zhǎng)寬,調(diào)用options.outWidth/outHeight獲取出圖片的寬高,然后通過(guò)一定的算法,即可得到適合的inSampleSize,這里感謝街神提供的代碼——摘自鴻洋blog!

public static int caculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    int width = options.outWidth;
    int height = options.outHeight;
    int inSampleSize = 1;
    if (width > reqWidth || height > reqHeight) {
        int widthRadio = Math.round(width * 1.0f / reqWidth);
        int heightRadio = Math.round(height * 1.0f / reqHeight);
        inSampleSize = Math.max(widthRadio, heightRadio);
    }
    return inSampleSize;
}

然后使用下上述的方法即可:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 設(shè)置了此屬性一定要記得將值設(shè)置為false
Bitmap bitmap = null;
bitmap = BitmapFactory.decodeFile(url, options);
options.inSampleSize = computeSampleSize(options,128,128);
options.inPreferredConfig = Bitmap.Config.ARGB_4444;
/* 下面兩個(gè)字段需要組合使用 */  
options.inPurgeable = true;
options.inInputShareable = true;
options.inJustDecodeBounds = false;
try {
    bitmap = BitmapFactory.decodeFile(url, options);
} catch (OutOfMemoryError e) {
        Log.e(TAG, "OutOfMemoryError");
}

3.及時(shí)回收?qǐng)D像

如果引用了大量的Bitmap對(duì)象,而應(yīng)用又不需要同時(shí)顯示所有圖片??梢詫簳r(shí)不用到的Bitmap對(duì)象及時(shí)回收掉。對(duì)于一些明確知道圖片使用情況的場(chǎng)景可以主動(dòng)recycle回收,比如引導(dǎo)頁(yè)的圖片,使用完就recycle,幀動(dòng)畫(huà),加載一張,畫(huà)一張,釋放一張!使用時(shí)加載,不顯示時(shí)直接置null或recycle!比如:imageView.setImageResource(0); 不過(guò)某些情況下會(huì)出現(xiàn)特定圖片反復(fù)加載,釋放,再加載等,低效率的事情...

4.其他方法

下面這些方法,我并沒(méi)有用過(guò),大家可以自行查閱相關(guān)資料:

1.簡(jiǎn)單通過(guò)SoftReference引用方式管理圖片資源

建個(gè)SoftReference的hashmap使用圖片時(shí)先查詢(xún)這個(gè)hashmap是否有softreference, softreference里的圖片是否為空,如果為空就加載圖片到softreference并加入hashmap。無(wú)需再代碼里顯式的處理圖片的回收與釋放,gc會(huì)自動(dòng)處理資源的釋放。這種方式處理起來(lái)簡(jiǎn)單實(shí)用,能一定程度上避免前一種方法反復(fù)加載釋放的低效率。但還不夠優(yōu)化。

示例代碼:

private Map<String, SoftReference<Bitmap>> imageMap 
                                           = new HashMap<String, SoftReference<Bitmap>>();

public Bitmap loadBitmap(final String imageUrl,final ImageCallBack imageCallBack) {
    SoftReference<Bitmap> reference = imageMap.get(imageUrl);
    if(reference != null) {
        if(reference.get() != null) {
            return reference.get();
        }
    }
    final Handler handler = new Handler() {
        public void handleMessage(final android.os.Message msg) {
            //加入到緩存中
            Bitmap bitmap = (Bitmap)msg.obj;
            imageMap.put(imageUrl, new SoftReference<Bitmap>(bitmap));
            if(imageCallBack != null) {
                imageCallBack.getBitmap(bitmap);
            }
        }
    };
    new Thread(){
        public void run() {
            Message message = handler.obtainMessage();
            message.obj = downloadBitmap(imageUrl);
            handler.sendMessage(message);
        }
    }.start();
    return null ;
}

// 從網(wǎng)上下載圖片
private Bitmap downloadBitmap (String imageUrl) {
    Bitmap bitmap = null;
    try {
        bitmap = BitmapFactory.decodeStream(new URL(imageUrl).openStream());
        return bitmap ;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    } 
}
public interface ImageCallBack{
    void getBitmap(Bitmap bitmap);
}

2.LruCache + sd的緩存方式

Android 3.1版本起,官方還提供了LruCache來(lái)進(jìn)行cache處理,當(dāng)存儲(chǔ)Image的大小大于LruCache 設(shè)定的值,那么近期使用次數(shù)最少的圖片就會(huì)被回收掉,系統(tǒng)會(huì)自動(dòng)釋放內(nèi)存!

使用示例

步驟:

1)要先設(shè)置緩存圖片的內(nèi)存大小,我這里設(shè)置為手機(jī)內(nèi)存的1/8,手機(jī)內(nèi)存的獲取方式:int MAXMEMONRY = (int) (Runtime.getRuntime() .maxMemory() / 1024);

2)LruCache里面的鍵值對(duì)分別是URL和對(duì)應(yīng)的圖片

3)重寫(xiě)了一個(gè)叫做sizeOf的方法,返回的是圖片數(shù)量。

private LruCache<String, Bitmap> mMemoryCache;
private LruCacheUtils() {
    if (mMemoryCache == null)
        mMemoryCache = new LruCache<String, Bitmap>(
                MAXMEMONRY / 8) {
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                // 重寫(xiě)此方法來(lái)衡量每張圖片的大小,默認(rèn)返回圖片數(shù)量。
                return bitmap.getRowBytes() * bitmap.getHeight() / 1024;
            }

            @Override
            protected void entryRemoved(boolean evicted, String key,
                    Bitmap oldValue, Bitmap newValue) {
                Log.v("tag", "hard cache is full , push to soft cache");
               
            }
        };
}

4)下面的方法分別是清空緩存、添加圖片到緩存、從緩存中取得圖片、從緩存中移除。

移除和清除緩存是必須要做的事,因?yàn)閳D片緩存處理不當(dāng)就會(huì)報(bào)內(nèi)存溢出,所以一定要引起注意。

public void clearCache() {
    if (mMemoryCache != null) {
        if (mMemoryCache.size() > 0) {
            Log.d("CacheUtils",
                    "mMemoryCache.size() " + mMemoryCache.size());
            mMemoryCache.evictAll();
            Log.d("CacheUtils", "mMemoryCache.size()" + mMemoryCache.size());
        }
        mMemoryCache = null;
    }
}

public synchronized void addBitmapToMemoryCache(String key, Bitmap bitmap) {
    if (mMemoryCache.get(key) == null) {
        if (key != null && bitmap != null)
            mMemoryCache.put(key, bitmap);
    } else
        Log.w(TAG, "the res is aready exits");
}

public synchronized Bitmap getBitmapFromMemCache(String key) {
    Bitmap bm = mMemoryCache.get(key);
    if (key != null) {
        return bm;
    }
    return null;
}

/**
 * 移除緩存
 * 
 * @param key
 */
public synchronized void removeImageCache(String key) {
    if (key != null) {
        if (mMemoryCache != null) {
            Bitmap bm = mMemoryCache.remove(key);
            if (bm != null)
                bm.recycle();
        }
    }
}

到此這篇關(guān)于Bitmap引起的OOM問(wèn)題的文章就介紹到這了,更多相關(guān)Bitmap OOM內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android Apt之Activity Route的示例

    Android Apt之Activity Route的示例

    本篇文章主要介紹了Android Apt之Activity Route的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • Android 實(shí)現(xiàn)微信,微博,微信朋友圈,QQ分享的功能

    Android 實(shí)現(xiàn)微信,微博,微信朋友圈,QQ分享的功能

    這篇文章主要介紹了Android 實(shí)現(xiàn)微信,微博,微信朋友圈,QQ分享的功能的相關(guān)資料,需要的朋友可以參考下
    2016-12-12
  • Android IPC機(jī)制Messenger實(shí)例詳解

    Android IPC機(jī)制Messenger實(shí)例詳解

    這篇文章主要介紹了 Android IPC機(jī)制Messenger實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • Android使用HBuilder的緩存方法

    Android使用HBuilder的緩存方法

    這篇文章主要介紹了Android使用HBuilder的緩存方法 ,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-12-12
  • Android實(shí)用的代碼片段 常用代碼總結(jié)

    Android實(shí)用的代碼片段 常用代碼總結(jié)

    這篇文章主要介紹了Android實(shí)用的代碼片段 常用代碼總結(jié),需要的朋友可以參考下
    2014-09-09
  • Flutter組件隱藏的多種方式總結(jié)

    Flutter組件隱藏的多種方式總結(jié)

    在 Flutter 開(kāi)發(fā)中,我們經(jīng)常會(huì)遇到需要?jiǎng)討B(tài)隱藏或顯示組件的需求,Flutter 提供了多種方式來(lái)實(shí)現(xiàn)這一功能,每種方式都有其獨(dú)特的適用場(chǎng)景,本文將深入探討這些方法的原理、用法以及優(yōu)缺點(diǎn),幫助您選擇最適合的方案,需要的朋友可以參考下
    2024-10-10
  • Android中利用C++處理Bitmap對(duì)象的實(shí)現(xiàn)方法

    Android中利用C++處理Bitmap對(duì)象的實(shí)現(xiàn)方法

    下面小編就為大家?guī)?lái)一篇Android中利用C++處理Bitmap對(duì)象的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • 如何玩轉(zhuǎn)Android矢量圖VectorDrawable

    如何玩轉(zhuǎn)Android矢量圖VectorDrawable

    這篇文章主要教大家如何玩轉(zhuǎn)Android矢量圖VectorDrawable,對(duì)矢量圖感興趣的小伙伴們可以參考一下
    2016-05-05
  • Android監(jiān)聽(tīng)Home鍵和Back鍵的區(qū)別介紹

    Android監(jiān)聽(tīng)Home鍵和Back鍵的區(qū)別介紹

    這篇文章主要介紹了Android監(jiān)聽(tīng)Home鍵和Back鍵的區(qū)別介紹,本文還同時(shí)給出了Home鍵監(jiān)聽(tīng)的實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2015-06-06
  • JetpackCompose Navigation導(dǎo)航實(shí)現(xiàn)流程

    JetpackCompose Navigation導(dǎo)航實(shí)現(xiàn)流程

    Navigation是Jetpack用于Android導(dǎo)航的組件,作用是處理頁(yè)面跳轉(zhuǎn),以及頁(yè)面跳轉(zhuǎn)過(guò)程中的交互。使用Navigation,你就需要為每個(gè)頁(yè)面設(shè)定一條唯一路徑,它是一個(gè)String常量,形式是DeepLink的樣子,從一個(gè)頁(yè)面跳轉(zhuǎn)到另一個(gè)頁(yè)面,它通過(guò)輸入目的地的路徑進(jìn)行轉(zhuǎn)跳
    2023-01-01

最新評(píng)論

岑巩县| 池州市| 娱乐| 吉水县| 宜良县| 甘德县| 乾安县| 嵊州市| 太仓市| 霍林郭勒市| 铜陵市| 阳谷县| 仙游县| 高雄市| 灵丘县| 宜宾市| 东山县| 临夏市| 临清市| 阿克苏市| 区。| 沙洋县| 布尔津县| 屏山县| 淮安市| 巴南区| 河曲县| 修武县| 长武县| 舒兰市| 团风县| 申扎县| 宝坻区| 孙吴县| 颍上县| 竹山县| 贞丰县| 左云县| 芮城县| 屏东县| 新绛县|