免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開(kāi)通VIP
[Android] Android開(kāi)發(fā)優(yōu)化之——對(duì)Bitmap的內(nèi)存優(yōu)化

在Android應(yīng)用里,最耗費(fèi)內(nèi)存的就是圖片資源。而且在Android系統(tǒng)中,讀取位圖Bitmap時(shí),分給虛擬機(jī)中的圖片的堆棧大小只有8M,如果超出了,就會(huì)出現(xiàn)OutOfMemory異常。所以,對(duì)于圖片的內(nèi)存優(yōu)化,是Android應(yīng)用開(kāi)發(fā)中比較重要的內(nèi)容。

 

1) 要及時(shí)回收Bitmap的內(nèi)存

Bitmap類有一個(gè)方法recycle(),從方法名可以看出意思是回收。這里就有疑問(wèn)了,Android系統(tǒng)有自己的垃圾回收機(jī)制,可以不定期的回收掉不使用的內(nèi)存空間,當(dāng)然也包括Bitmap的空間。那為什么還需要這個(gè)方法呢?

Bitmap類的構(gòu)造方法都是私有的,所以開(kāi)發(fā)者不能直接new出一個(gè)Bitmap對(duì)象,只能通過(guò)BitmapFactory類的各種靜態(tài)方法來(lái)實(shí)例化一個(gè)Bitmap。仔細(xì)查看BitmapFactory的源代碼可以看到,生成Bitmap對(duì)象最終都是通過(guò)JNI調(diào)用方式實(shí)現(xiàn)的。所以,加載Bitmap到內(nèi)存里以后,是包含兩部分內(nèi)存區(qū)域的。簡(jiǎn)單的說(shuō),一部分是Java部分的,一部分是C部分的。這個(gè)Bitmap對(duì)象是由Java部分分配的,不用的時(shí)候系統(tǒng)就會(huì)自動(dòng)回收了,但是那個(gè)對(duì)應(yīng)的C可用的內(nèi)存區(qū)域,虛擬機(jī)是不能直接回收的,這個(gè)只能調(diào)用底層的功能釋放。所以需要調(diào)用recycle()方法來(lái)釋放C部分的內(nèi)存。從Bitmap類的源代碼也可以看到,recycle()方法里也的確是調(diào)用了JNI方法了的。

那如果不調(diào)用recycle(),是否就一定存在內(nèi)存泄露呢?也不是的。Android的每個(gè)應(yīng)用都運(yùn)行在獨(dú)立的進(jìn)程里,有著獨(dú)立的內(nèi)存,如果整個(gè)進(jìn)程被應(yīng)用本身或者系統(tǒng)殺死了,內(nèi)存也就都被釋放掉了,當(dāng)然也包括C部分的內(nèi)存。

Android對(duì)于進(jìn)程的管理是非常復(fù)雜的。簡(jiǎn)單的說(shuō),Android系統(tǒng)的進(jìn)程分為幾個(gè)級(jí)別,系統(tǒng)會(huì)在內(nèi)存不足的情況下殺死一些低優(yōu)先級(jí)的進(jìn)程,以提供給其它進(jìn)程充足的內(nèi)存空間。在實(shí)際項(xiàng)目開(kāi)發(fā)過(guò)程中,有的開(kāi)發(fā)者會(huì)在退出程序的時(shí)候使用Process.killProcess(Process.myPid())的方式將自己的進(jìn)程殺死,但是有的應(yīng)用僅僅會(huì)使用調(diào)用Activity.finish()方法的方式關(guān)閉掉所有的Activity。

 

經(jīng)驗(yàn)分享:

Android手機(jī)的用戶,根據(jù)習(xí)慣不同,可能會(huì)有兩種方式退出整個(gè)應(yīng)用程序:一種是按Home鍵直接退到桌面;另一種是從應(yīng)用程序的退出按鈕或者按Back鍵退出程序。那么從系統(tǒng)的角度來(lái)說(shuō),這兩種方式有什么區(qū)別呢?按Home鍵,應(yīng)用程序并沒(méi)有被關(guān)閉,而是成為了后臺(tái)應(yīng)用程序。按Back鍵,一般來(lái)說(shuō),應(yīng)用程序關(guān)閉了,但是進(jìn)程并沒(méi)有被殺死,而是成為了空進(jìn)程(程序本身對(duì)退出做了特殊處理的不考慮在內(nèi))。

Android系統(tǒng)已經(jīng)做了大量進(jìn)程管理的工作,這些已經(jīng)可以滿足用戶的需求。個(gè)人建議,應(yīng)用程序在退出應(yīng)用的時(shí)候不需要手動(dòng)殺死自己所在的進(jìn)程。對(duì)于應(yīng)用程序本身的進(jìn)程管理,交給Android系統(tǒng)來(lái)處理就可以了。應(yīng)用程序需要做的,是盡量做好程序本身的內(nèi)存管理工作。

 

一般來(lái)說(shuō),如果能夠獲得Bitmap對(duì)象的引用,就需要及時(shí)的調(diào)用Bitmap的recycle()方法來(lái)釋放Bitmap占用的內(nèi)存空間,而不要等Android系統(tǒng)來(lái)進(jìn)行釋放。

下面是釋放Bitmap的示例代碼片段。

// 先判斷是否已經(jīng)回收

if(bitmap != null && !bitmap.isRecycled()){ 

        // 回收并且置為null

        bitmap.recycle(); 

        bitmap = null; 

System.gc();

 

從上面的代碼可以看到,bitmap.recycle()方法用于回收該Bitmap所占用的內(nèi)存,接著將bitmap置空,最后使用System.gc()調(diào)用一下系統(tǒng)的垃圾回收器進(jìn)行回收,可以通知垃圾回收器盡快進(jìn)行回收。這里需要注意的是,調(diào)用System.gc()并不能保證立即開(kāi)始進(jìn)行回收過(guò)程,而只是為了加快回收的到來(lái)。

如何調(diào)用recycle()方法進(jìn)行回收已經(jīng)了解了,那什么時(shí)候釋放Bitmap的內(nèi)存比較合適呢?一般來(lái)說(shuō),如果代碼已經(jīng)不再需要使用Bitmap對(duì)象了,就可以釋放了。釋放內(nèi)存以后,就不能再使用該Bitmap對(duì)象了,如果再次使用,就會(huì)拋出異常。所以一定要保證不再使用的時(shí)候釋放。比如,如果是在某個(gè)Activity中使用Bitmap,就可以在Activity的onStop()或者onDestroy()方法中進(jìn)行回收。

 

2) 捕獲異常

因?yàn)锽itmap是吃內(nèi)存大戶,為了避免應(yīng)用在分配Bitmap內(nèi)存的時(shí)候出現(xiàn)OutOfMemory異常以后Crash掉,需要特別注意實(shí)例化Bitmap部分的代碼。通常,在實(shí)例化Bitmap的代碼中,一定要對(duì)OutOfMemory異常進(jìn)行捕獲。

以下是代碼示例。

Bitmap bitmap = null;

try {

    // 實(shí)例化Bitmap

    bitmap = BitmapFactory.decodeFile(path);

} catch (OutOfMemoryError e) {

    //

}

if (bitmap == null) {

    // 如果實(shí)例化失敗 返回默認(rèn)的Bitmap對(duì)象

    return defaultBitmapMap;

}

 

這里對(duì)初始化Bitmap對(duì)象過(guò)程中可能發(fā)生的OutOfMemory異常進(jìn)行了捕獲。如果發(fā)生了OutOfMemory異常,應(yīng)用不會(huì)崩潰,而是得到了一個(gè)默認(rèn)的Bitmap圖。

 

經(jīng)驗(yàn)分享:

    很多開(kāi)發(fā)者會(huì)習(xí)慣性的在代碼中直接捕獲Exception。但是對(duì)于OutOfMemoryError來(lái)說(shuō),這樣做是捕獲不到的。因?yàn)镺utOfMemoryError是一種Error,而不是Exception。在此僅僅做一下提醒,避免寫錯(cuò)代碼而捕獲不到OutOfMemoryError。

 

3) 緩存通用的Bitmap對(duì)象

有時(shí)候,可能需要在一個(gè)Activity里多次用到同一張圖片。比如一個(gè)Activity會(huì)展示一些用戶的頭像列表,而如果用戶沒(méi)有設(shè)置頭像的話,則會(huì)顯示一個(gè)默認(rèn)頭像,而這個(gè)頭像是位于應(yīng)用程序本身的資源文件中的。

如果有類似上面的場(chǎng)景,就可以對(duì)同一Bitmap進(jìn)行緩存。如果不進(jìn)行緩存,盡管看到的是同一張圖片文件,但是使用BitmapFactory類的方法來(lái)實(shí)例化出來(lái)的Bitmap,是不同的Bitmap對(duì)象。緩存可以避免新建多個(gè)Bitmap對(duì)象,避免內(nèi)存的浪費(fèi)。

 

經(jīng)驗(yàn)分享:

    Web開(kāi)發(fā)者對(duì)于緩存技術(shù)是很熟悉的。其實(shí)在Android應(yīng)用開(kāi)發(fā)過(guò)程中,也會(huì)經(jīng)常使用緩存的技術(shù)。這里所說(shuō)的緩存有兩個(gè)級(jí)別,一個(gè)是硬盤緩存,一個(gè)是內(nèi)存緩存。比如說(shuō),在開(kāi)發(fā)網(wǎng)絡(luò)應(yīng)用過(guò)程中,可以將一些從網(wǎng)絡(luò)上獲取的數(shù)據(jù)保存到SD卡中,下次直接從SD卡讀取,而不從網(wǎng)絡(luò)中讀取,從而節(jié)省網(wǎng)絡(luò)流量。這種方式就是硬盤緩存。再比如,應(yīng)用程序經(jīng)常會(huì)使用同一對(duì)象,也可以放到內(nèi)存中緩存起來(lái),需要的時(shí)候直接從內(nèi)存中讀取。這種方式就是內(nèi)存緩存。

 

4) 壓縮圖片

如果圖片像素過(guò)大,使用BitmapFactory類的方法實(shí)例化Bitmap的過(guò)程中,需要大于8M的內(nèi)存空間,就必定會(huì)發(fā)生OutOfMemory異常。這個(gè)時(shí)候該如何處理呢?如果有這種情況,則可以將圖片縮小,以減少載入圖片過(guò)程中的內(nèi)存的使用,避免異常發(fā)生。

使用BitmapFactory.Options設(shè)置inSampleSize就可以縮小圖片。屬性值inSampleSize表示縮略圖大小為原始圖片大小的幾分之一。即如果這個(gè)值為2,則取出的縮略圖的寬和高都是原始圖片的1/2,圖片的大小就為原始大小的1/4。

如果知道圖片的像素過(guò)大,就可以對(duì)其進(jìn)行縮小。那么如何才知道圖片過(guò)大呢?

使用BitmapFactory.Options設(shè)置inJustDecodeBounds為true后,再使用decodeFile()等方法,并不會(huì)真正的分配空間,即解碼出來(lái)的Bitmap為null,但是可計(jì)算出原始圖片的寬度和高度,即options.outWidth和options.outHeight。通過(guò)這兩個(gè)值,就可以知道圖片是否過(guò)大了。

    BitmapFactory.Options opts = new BitmapFactory.Options();

    // 設(shè)置inJustDecodeBounds為true

    opts.inJustDecodeBounds = true;

    // 使用decodeFile方法得到圖片的寬和高

    BitmapFactory.decodeFile(path, opts);

    // 打印出圖片的寬和高

    Log.d("example", opts.outWidth + "," + opts.outHeight);

 

在實(shí)際項(xiàng)目中,可以利用上面的代碼,先獲取圖片真實(shí)的寬度和高度,然后判斷是否需要跑縮小。如果不需要縮小,設(shè)置inSampleSize的值為1。如果需要縮小,則動(dòng)態(tài)計(jì)算并設(shè)置inSampleSize的值,對(duì)圖片進(jìn)行縮小。需要注意的是,在下次使用BitmapFactory的decodeFile()等方法實(shí)例化Bitmap對(duì)象前,別忘記將opts.inJustDecodeBound設(shè)置回false。否則獲取的bitmap對(duì)象還是null。

 

經(jīng)驗(yàn)分享:

如果程序的圖片的來(lái)源都是程序包中的資源,或者是自己服務(wù)器上的圖片,圖片的大小是開(kāi)發(fā)者可以調(diào)整的,那么一般來(lái)說(shuō),就只需要注意使用的圖片不要過(guò)大,并且注意代碼的質(zhì)量,及時(shí)回收Bitmap對(duì)象,就能避免OutOfMemory異常的發(fā)生。

如果程序的圖片來(lái)自外界,這個(gè)時(shí)候就特別需要注意OutOfMemory的發(fā)生。一個(gè)是如果載入的圖片比較大,就需要先縮?。涣硪粋€(gè)是一定要捕獲異常,避免程序Crash。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
android加載大量圖片內(nèi)存溢出的三種解決辦法
ANDROID內(nèi)存優(yōu)化(大匯總
圖片緩存之內(nèi)存緩存技術(shù)LruCache,軟引用
圖片處理OOM總結(jié)
Android高效加載大圖、多圖解決方案,有效避免程序OOM
如何解決加載大圖片時(shí)內(nèi)存溢出的問(wèn)題
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服