bitmapandroid
Ⅰ android怎麼壓縮一個bitmap佔用空間大小
在Android應用里,最耗費內存的就是圖片資源。而且在Android系統中,讀取點陣圖Bitmap時,分給虛擬機中的圖片的堆棧大小隻有8M,如果超出了,就會出現OutOfMemory異常。所以,對於圖片的內存優化,是Android應用開發中比較重要的內容。 1) 要及時回收Bitmap的內存 Bitmap類有一個方法recycle(),從方法名可以看出意思是回收。這里就有疑問了,Android系統有自己的垃圾回收機制,可以不定期的回收掉不使用的內存空間,當然也包括Bitmap的空間。那為什麼還需要這個方法呢? Bitmap類的構造方法都是私有的,所以開發者不能直接new出一個Bitmap對象,只能通過BitmapFactory類的各種靜態方法來實例化一個Bitmap。仔細查看BitmapFactory的源代碼可以看到,生成Bitmap對象最終都是通過JNI調用方式實現的。所以,載入Bitmap到內存里以後,是包含兩部分內存區域的。簡單的說,一部分是java部分的,一部分是C部分的。這個Bitmap對象是由Java部分分配的,不用的時候系統就會自動回收了,但是那個對應的C可用的內存區域,虛擬機是不能直接回收的,這個只能調用底層的功能釋放。所以需要調用recycle()方法來釋放C部分的內存。從Bitmap類的源代碼也可以看到,recycle()方法里也的確是調用了JNI方法了的。 那如果不調用recycle(),是否就一定存在內存泄露呢?也不是的。Android的每個應用都運行在獨立的進程里,有著獨立的內存,如果整個進程被應用本身或者系統殺死了,內存也就都被釋放掉了,當然也包括C部分的內存。 Android對於進程的管理是非常復雜的。簡單的說,Android系統的進程分為幾個級別,系統會在內存不足的情況下殺死一些低優先順序的進程,以提供給其它進程充足的內存空間。在實際項目開發過程中,有的開發者會在退出程序的時候使用Process.killProcess(Process.myPid())的方式將自己的進程殺死,但是有的應用僅僅會使用調用Activity.finish()方法的方式關閉掉所有的Activity。 經驗分享: Android手機的用戶,根據習慣不同,可能會有兩種方式退出整個應用程序:一種是按Home鍵直接退到桌面;另一種是從應用程序的退出按鈕或者按Back鍵退出程序。那麼從系統的角度來說,這兩種方式有什麼區別呢?按Home鍵,應用程序並沒有被關閉,而是成為了後台應用程序。按Back鍵,一般來說,應用程序關閉了,但是進程並沒有被殺死,而是成為了空進程(程序本身對退出做了特殊處理的不考慮在內)。 Android系統已經做了大量進程管理的工作,這些已經可以滿足用戶的需求。個人建議,應用程序在退出應用的時候不需要手動殺死自己所在的進程。對於應用程序本身的進程管理,交給Android系統來處理就可以了。應用程序需要做的,是盡量做好程序本身的內存管理工作。 一般來說,如果能夠獲得Bitmap對象的引用,就需要及時的調用Bitmap的recycle()方法來釋放Bitmap佔用的內存空間,而不要等Android系統來進行釋放。 下面是釋放Bitmap的示例代碼片段。 // 先判斷是否已經回收 if(bitmap != null && !bitmap.isRecycled()){ // 回收並且置為null bitmap.recycle(); bitmap = null; } System.gc(); 從上面的代碼可以看到,bitmap.recycle()方法用於回收該Bitmap所佔用的內存,接著將bitmap置空,最後使用System.gc()調用一下系統的垃圾回收器進行回收,可以通知垃圾回收器盡快進行回收。這里需要注意的是,調用System.gc()並不能保證立即開始進行回收過程,而只是為了加快回收的到來。 如何調用recycle()方法進行回收已經了解了,那什麼時候釋放Bitmap的內存比較合適呢?一般來說,如果代碼已經不再需要使用Bitmap對象了,就可以釋放了。釋放內存以後,就不能再使用該Bitmap對象了,如果再次使用,就會拋出異常。所以一定要保證不再使用的時候釋放。比如,如果是在某個Activity中使用Bitmap,就可以在Activity的onStop()或者onDestroy()方法中進行回收。 2) 捕獲異常 因為Bitmap是吃內存大戶,為了避免應用在分配Bitmap內存的時候出現OutOfMemory異常以後Crash掉,需要特別注意實例化Bitmap部分的代碼。通常,在實例化Bitmap的代碼中,一定要對OutOfMemory異常進行捕獲。 以下是代碼示例。 Bitmap bitmap = null; try { // 實例化Bitmap bitmap = BitmapFactory.decodeFile(path); } catch (OutOfMemoryError e) { // } if (bitmap == null) { // 如果實例化失敗 返回默認的Bitmap對象 return defaultBitmapMap; } 這里對初始化Bitmap對象過程中可能發生的OutOfMemory異常進行了捕獲。如果發生了OutOfMemory異常,應用不會崩潰,而是得到了一個默認的Bitmap圖。 經驗分享: 很多開發者會習慣性的在代碼中直接捕獲Exception。但是對於OutOfMemoryError來說,這樣做是捕獲不到的。因為OutOfMemoryError是一種Error,而不是Exception。在此僅僅做一下提醒,避免寫錯代碼而捕獲不到OutOfMemoryError。 3) 緩存通用的Bitmap對象 有時候,可能需要在一個Activity里多次用到同一張圖片。比如一個Activity會展示一些用戶的頭像列表,而如果用戶沒有設置頭像的話,則會顯示一個默認頭像,而這個頭像是位於應用程序本身的資源文件中的。 如果有類似上面的場景,就可以對同一Bitmap進行緩存。如果不進行緩存,盡管看到的是同一張圖片文件,但是使用BitmapFactory類的方法來實例化出來的Bitmap,是不同的Bitmap對象。緩存可以避免新建多個Bitmap對象,避免內存的浪費。 經驗分享: Web開發者對於緩存技術是很熟悉的。其實在Android應用開發過程中,也會經常使用緩存的技術。這里所說的緩存有兩個級別,一個是硬碟緩存,一個是內存緩存。比如說,在開發網路應用過程中,可以將一些從網路上獲取的數據保存到SD卡中,下次直接從SD卡讀取,而不從網路中讀取,從而節省網路流量。這種方式就是硬碟緩存。再比如,應用程序經常會使用同一對象,也可以放到內存中緩存起來,需要的時候直接從內存中讀取。這種方式就是內存緩存。 4) 壓縮圖片 如果圖片像素過大,使用BitmapFactory類的方法實例化Bitmap的過程中,需要大於8M的內存空間,就必定會發生OutOfMemory異常。這個時候該如何處理呢?如果有這種情況,則可以將圖片縮小,以減少載入圖片過程中的內存的使用,避免異常發生。 使用BitmapFactory.Options設置inSampleSize就可以縮小圖片。屬性值inSampleSize表示縮略圖大小為原始圖片大小的幾分之一。即如果這個值為2,則取出的縮略圖的寬和高都是原始圖片的1/2,圖片的大小就為原始大小的1/4。 如果知道圖片的像素過大,就可以對其進行縮小。那麼如何才知道圖片過大呢? 使用BitmapFactory.Options設置inJustDecodeBounds為true後,再使用decodeFile()等方法,並不會真正的分配空間,即解碼出來的Bitmap為null,但是可計算出原始圖片的寬度和高度,即options.outWidth和options.outHeight。通過這兩個值,就可以知道圖片是否過大了。 BitmapFactory.Options opts = new BitmapFactory.Options(); // 設置inJustDecodeBounds為true opts.inJustDecodeBounds = true; // 使用decodeFile方法得到圖片的寬和高 BitmapFactory.decodeFile(path, opts); // 列印出圖片的寬和高 Log.d("example", opts.outWidth + "," + opts.outHeight); 在實際項目中,可以利用上面的代碼,先獲取圖片真實的寬度和高度,然後判斷是否需要跑縮小。如果不需要縮小,設置inSampleSize的值為1。如果需要縮小,則動態計算並設置inSampleSize的值,對圖片進行縮小。需要注意的是,在下次使用BitmapFactory的decodeFile()等方法實例化Bitmap對象前,別忘記將opts.inJustDecodeBound設置回false。否則獲取的bitmap對象還是null。 經驗分享: 如果程序的圖片的來源都是程序包中的資源,或者是自己伺服器上的圖片,圖片的大小是開發者可以調整的,那麼一般來說,就只需要注意使用的圖片不要過大,並且注意代碼的質量,及時回收Bitmap對象,就能避免OutOfMemory異常的發生。 如果程序的圖片來自外界,這個時候就特別需要注意OutOfMemory的發生。一個是如果載入的圖片比較大,就需要先縮小;另一個是一定要捕獲異常,避免程序Crash。
Ⅱ android bitmap闆嗗悎鎬庝箞閲婃斁錛岀洿鎺clear錛屽彲浠ュ悧
浠婂ぉ鏉ョ爺絀朵竴涓媋ndroid涓鐨凚itmap銆傚湪瀹為檯寮鍙戜腑錛孊itmap緇忓父鐢ㄥ埌錛岀壒鍒鏄娓告垙寮鍙戙傚彲浠ヨ存父鎴忓紑鍙戝叾瀹炲氨鏄瀵瑰浘鐗囷紙Bitmap錛夋搷浣滐紒鍙瑙丅itmap鏈夊氶噸瑕併傝繖閲屾垜浠涓昏佽ㄨ虹殑鏄疊itmap璧勬簮閲婃斁鍘熺悊銆
鎴戜滑鐭ラ亾錛岀敤瀹屼竴涓狟itmap鍚庯紝闇瑕侀┈涓妑ecycle()鏉ヤ繚璇佸敖蹇閲婃斁鏈熻祫婧愩傞栧厛錛屾垜浠鏉ョ湅鐪媟ecycle()榪欎釜鍑芥暟鐨勫畾涔夛紙Bitmap.java錛夛細
[java] view plain
public void recycle() {
if (!mRecycled) {
if (nativeRecycle(mNativeBitmap)) {
// return value indicates whether native pixel object was actually recycled.
// false indicates that it is still in use at the native level and these
// objects should not be collected now. They will be collected later when the
// Bitmap itself is collected.
mBuffer = null;
mNinePatchChunk = null;
}
mRecycled = true;
}
}
浠g爜寰堢畝鍗曪紝涓昏佽皟鐢ㄨ繖涓鍑芥暟錛歯ativeRecycle(mNativeBitmap)鍘婚噴鏀俱傝繖閲屾槸JNI鏂瑰紡鍘昏皟鐢ㄤ簡c鍐欑殑鏂規硶錛佸叾瀹烇紝浣犵湅鐪嬩竴涓婤itmap榪欎釜綾伙紝灝辯煡閬撲簡錛屽叾瀹濨itmap鐨勫疄鐜頒富瑕侀兘鏄鐢–鍐欑殑錛屼負浜嗕繚璇佹晥鐜囪繖鏍烽夋嫨鏄蹇呯劧鐨勶紒 榪欎笉鏄鎴戜滑璁ㄨ虹殑閲嶇偣銆傛垜浠鏉ョ湅鐪媑oogle緇欒繖涓鍑芥暟鐨勪竴孌佃存槑錛
[java] view plain
/**
* Free the native object associated with this bitmap, and clear the
* reference to the pixel data. This will not free the pixel data synchronously;
* it simply allows it to be garbage collected if there are no other references.
* The bitmap is marked as "dead", meaning it will throw an exception if
* getPixels() or setPixels() is called, and will draw nothing. This operation
* cannot be reversed, so it should only be called if you are sure there are no
* further uses for the bitmap. This is an advanced call, and normally need
* not be called, since the normal GC process will free up this memory when
* there are no more references to this bitmap.
*/
閫氳繃榪欐佃存槑鎴戜滑鐭ラ亾璋冪敤榪欎釜鍑芥暟鍏跺疄鍙鏄浼歠ree涓浜涚浉鍏崇殑璧勬簮銆佸逛簬鍏秚鍥劇墖鍍忕礌鏁版嵁騫舵病鏈夊悓姝ラ噴鏀撅紝鑰屼笖榪欎釜鏂規硶閫氬父涔熶笉鏄蹇呰佺殑錛屽氨鏄璇達細涓嶆槸涓瀹氳佽皟鐢ㄨ繖涓鍑芥暟榪欎釜Bitmap鎵嶄細琚獹C鍥炴敹銆傞偅涔堥棶棰樺氨鏉ヤ簡錛氬垰鎵嶈翠簡錛岄偅鍥劇墖鍍忕礌榪欑被鏁版嵁鏄濡備綍閲婃斁鐨勫憿錛熸渶閲嶈佺殑鏄痓itmap澶勭悊鐨勬牳蹇冧唬鐮佷笉鏄疛AVA鍐欑殑銆
榪欎釜鏃跺檉inalize()灝辯櫥鍦轟簡銆傛垜浠鍏堢湅鐪嬮噷闈㈠畾涔夌殑涓涓縐佹湁鍙橀噺private final BitmapFinalizer mFinalizer; BitmapFinalizer 鏄疊itmap鐨勫唴閮ㄧ被錛
[java] view plain
private static class BitmapFinalizer {
private final int mNativeBitmap;
BitmapFinalizer(int nativeBitmap) {
mNativeBitmap = nativeBitmap;
}
@Override
public void finalize() {
try {
super.finalize();
} catch (Throwable t) {
// Ignore
} finally {
nativeDestructor(mNativeBitmap);
}
}
}
榪欓噷寰堝ソ鐨勫埄鐢╫bject鐨刦inalize()榪欎釜鍥炶皟鍑芥暟錛屽畨鍗撳崥瀹http://www.bafenbaosoft.com 榪欐牱灝辨潵淇濊瘉涓涓狟itmap瀵硅薄琚閲婃斁鐨勬椂鍊欒兘澶熷洖璋僾oid nativeDestructor(int nativeBitmap);榪欎釜鍑芥暟鏉ラ噴鏀綜閲岄潰鐢寵風殑璧勬簮錛
Ⅲ android bitmap 浣跨敤鏃跺欐敞鎰忎粈涔
涓銆 闂棰樼殑鑳屾櫙鍜屾剰涔
鍦ˋndroid縐誨姩搴旂敤寮鍙戜腑錛屽笲itmap鐨勪笉灝忓績澶勭悊錛屽緢瀹規槗寮曡搗紼嬪簭鍐呭瓨絀洪棿鑰楀敖鑰屽艱嚧鐨勭▼搴忓穿婧冮棶棰樸傛瘮濡傛垜浠甯擱亣鍒扮殑闂棰橈細
java.lang.OutofMemoryError: bitmap size exceeds VM budget.
瀵艱嚧璇ラ棶棰樼殑鍑虹幇錛屼竴鑸鐢變互涓嬪嚑鏂歸潰鍘熷洜瀵艱嚧錛
寮曞姩璁懼囦竴鑸瀛樺偍絀洪棿闈炲父鏈夐檺銆傚綋鐒朵笉鍚岃懼囧垎閰嶇粰搴旂敤鐨勫唴瀛樼┖闂存槸涓嶅悓鐨勩備絾鐩稿逛笉浣嗘彁楂樼殑璁懼囧垎杈ㄧ巼鑰岃█錛屽唴瀛樼殑鍒嗛厤浠嶇劧鏄鐩稿圭揣寮犵殑銆
Bitmap瀵硅薄甯稿父鍗犵敤澶ч噺鐨勫唴瀛樼┖闂達紝姣斿傦細瀵逛簬2592*1936鐨勮懼囷紝濡傛灉閲囩敤ARGB_8888鐨勬牸寮忓姞杞藉浘鍍忥紝鍐呭瓨鍗犵敤灝嗚揪鍒19MB絀洪棿銆
鍦ˋnroid App涓緇忓父鐢ㄥ埌ListView錛孷iewPager絳夋帶浠訛紝榪欎簺鎺т歡甯鎬細鍖呭惈杈冨ぇ鏁伴噺鐨勫浘鐗囪祫婧愩
浜屻 闂棰樺強鍦烘櫙鍒嗘瀽
1 楂樻晥鍦板姞杞藉ぇ鍥劇墖銆
BitmapFactory綾繪彁渚涗簡涓浜涘姞杞藉浘鐗囩殑鏂規硶錛歞ecodeByteArray(), decodeFile(), decodeResource(), 絳夌瓑銆
涓轟簡閬垮厤鍗犵敤杈冨ぇ鍐呭瓨錛岀粡甯鎬嬌鐢˙itmapFactory.Options 綾伙紝璁劇疆inJustDecodeBounds灞炴т負true銆
//
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds =true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
涓轟簡閬垮厤java.lang.OutOfMemory 鐨勫紓甯革紝鎴戜滑鍦ㄧ湡姝decode鍥劇墖涔嬪墠媯鏌ュ畠鐨勫昂瀵革紝闄ら潪浣犵『瀹氳繖涓鏁版嵁婧愭彁渚涗簡鍑嗙『鏃犺鐨勫浘鐗囦笖涓嶄細瀵艱嚧鍗犵敤榪囧氱殑鍐呭瓨銆
鍔犺澆涓涓鎸夋瘮渚嬬緝灝忕殑鐗堟湰鍒板唴瀛樹腑銆備緥濡傦紝濡傛灉鎶婁竴涓鍘熷浘鏄1024*768 pixel鐨勫浘鐗囨樉紺哄埌ImageView涓128*96 pixel鐨勭緝鐣ュ浘灝辨病鏈夊繀瑕佹妸鏁村紶鍥劇墖閮藉姞杞藉埌鍐呭瓨涓銆備負浜嗗憡璇夎В鐮佸櫒鍘誨姞杞戒竴涓杈冨皬鐨勫浘鐗囧埌鍐呭瓨錛岄渶瑕佸湪浣犵殑BitmapFactory.Options 涓璁劇疆 inSampleSize 涓簍rue 銆備緥濡, 涓涓鍒嗚鯨鐜囦負2048x1536 鐨勫浘鐗囷紝濡傛灉璁劇疆inSampleSize 涓4錛岄偅涔堜細浜у嚭涓涓澶ф備負512x384鐨勫浘鐗囥傚姞杞借繖寮犲皬鐨勫浘鐗囦粎浠呬嬌鐢ㄥぇ姒0.75MB錛屽傛灉鏄鍔犺澆鍏ㄥ浘閭d箞澶ф傝佽姳璐12MB(鍋囪綽itmap鐨勯厤緗鏄疉RGB_8888).
2 涓嶈佸湪涓葷嚎紼嬪勭悊鍥劇墖銆
浼楁墍鍛ㄧ煡鐨勯棶棰橈紝涓嶅啀璧樿堪銆
娉ㄦ剰涓ょ偣錛1. 涓轟簡淇濊瘉浣跨敤鐨勮祫婧愯兘琚鍥炴敹錛屽緩璁浣跨敤WeakReference, 浠ュ簲鐢ㄥ唴瀛樺唴瀛樼揣寮犳椂錛屽洖鏀墮儴鍒嗚祫婧愶紝淇濊瘉紼嬪簭榪涚▼涓嶈鏉姝匯
2. 閬垮厤寮傛ヤ換鍔$殑闀挎椂闂磋楁椂鎿嶄綔錛屽湪浠誨姟鎵ц岀粨鏉熷悗錛屽強鏃墮噴鏀捐祫婧愩
3 綆$悊Bitmap鍐呭瓨銆
鍦ˋndroid寮鍙戜腑錛屽姞杞戒竴涓鍥劇墖鍒扮晫闈㈠緢瀹規槗錛屼絾濡傛灉涓嬈″姞杞藉ぇ閲忓浘鐗囧氨澶嶆潅澶氫簡銆傚湪寰堝氭儏鍐典笅錛堟瘮濡傦細ListView,GridView鎴朧iewPager錛夛紝鑳藉熸粴鍔ㄧ殑緇勪歡闇瑕佸姞杞界殑鍥劇墖鍑犱箮鏄鏃犻檺澶氱殑銆
鏈変簺緇勪歡鐨刢hild view鍦ㄤ笉鏄劇ず鏃朵細鍥炴敹錛屽苟寰鐜浣跨敤錛屽傛灉娌℃湁浠諱綍瀵筨itmap鐨勬寔涔呭紩鐢ㄧ殑璇濓紝鍨冨溇鍥炴敹鍣ㄤ細閲婃斁浣犲姞杞界殑bitmap銆傝繖娌′粈涔堥棶棰橈紝浣嗗綋榪欎簺鍥劇墖鍐嶆℃樉紺虹殑鏃跺欙紝瑕佹兂閬垮厤閲嶅嶅勭悊榪欎簺鍥劇墖錛屼粠鑰岃揪鍒板姞杞芥祦鐣呯殑鏁堟灉錛屽氨瑕佷嬌鐢ㄥ唴瀛樼紦瀛樺拰鏈鍦扮紦瀛樹簡錛岃繖浜涚紦瀛樺彲浠ヨ╀綘蹇閫熷姞杞藉勭悊榪囩殑鍥劇墖銆
3.1 鍐呭瓨緙撳瓨
鍐呭瓨緙撳瓨浠ョ壓鐗插唴瀛樼殑浠d環錛屽甫鏉ュ揩閫熺殑鍥劇墖璁塊棶銆侺ruCache綾伙紙API Level 4涔嬪墠鍙浠ヤ嬌鐢⊿upport Library錛夐潪甯擱傚悎鍥劇墖緙撳瓨浠誨姟錛屽湪涓涓狶inkedHashMap涓淇濆瓨鐫瀵笲itmap鐨勫己寮曠敤錛屽綋緙撳瓨鏁伴噺瓚呰繃瀹瑰櫒瀹歸噺鏃訛紝鍒犻櫎鏈榪戞渶灝戜嬌鐢ㄧ殑鎴愬憳錛圠RU錛夈
娉ㄦ剰錛氬湪榪囧幓錛岄潪甯告祦琛岀敤SoftReference鎴朩eakReference鏉ュ疄鐜板浘鐗囩殑鍐呭瓨緙撳瓨錛屼絾鐜板湪涓嶅啀鎺ㄨ崘浣跨敤榪欎釜鏂規硶浜嗐傚洜涓轟粠Android 2.3 錛圓PI Level 9錛変箣鍚庯紝鍨冨溇鍥炴敹鍣ㄤ細鏇寸Н鏋佺殑鍥炴敹soft/weak鐨勫紩鐢錛岃繖灝嗗艱嚧浣跨敤soft/weak寮曠敤鐨勭紦瀛樺嚑涔庢病鏈夌紦瀛樻晥鏋溿傞『甯︿竴鎻愶紝鍦ˋndroid3.0錛圓PI Level 11錛変互鍓嶏紝bitmap鏄鍌ㄥ瓨鍦╪ative 鍐呭瓨涓鐨勶紝鎵浠ョ郴緇熶互涓嶅彲棰勮佺殑鏂瑰紡鏉ラ噴鏀綽itmap錛岃繖鍙鑳戒細瀵艱嚧鐭鏃墮棿瓚呰繃鍐呭瓨闄愬埗浠庤岄犳垚宕╂簝銆 鏀惰搗
Ⅳ 瀹夊崜bitmap鍚堝苟鍑虹幇鑺卞睆
鑺卞睆鐜拌薄閫氬父鏄鐢變簬鍥懼儚鍚堝苟鎴栧勭悊榪囩▼涓瀛樺湪鐨勯棶棰樺紩璧風殑銆備互涓嬫槸涓浜涘彲鑳藉艱嚧鑺卞睆鐨勫父瑙佸師鍥犲拰瑙e喅鏂規硶錛
1. 鍥懼儚璐ㄩ噺闂棰橈細濡傛灉璐ㄩ噺杈冧綆鐨勫浘鍍忚鍚堝苟錛屽彲鑳戒細瀵艱嚧鑺卞睆銆傚彲浠ュ皾璇曚嬌鐢ㄩ珮璐ㄩ噺鐨勫浘鍍忚繘琛屽悎騫躲
2. 鍐呭瓨涓嶈凍錛氬傛灉鍚堝苟榪囩▼涓鍗犵敤鐨勫唴瀛樿秴榪囦簡璁懼囩殑鍙鐢ㄥ唴瀛橀檺鍒訛紝鍙鑳戒細瀵艱嚧鑺卞睆銆傚彲浠ュ皾璇曞噺灝忓浘鍍忓昂瀵告垨浼樺寲鍐呭瓨浣跨敤銆
3. 鍥懼儚鏍煎紡涓嶅吋瀹癸細濡傛灉鍚堝苟鐨勫浘鍍忔牸寮忎笉鍏煎癸紝鍙鑳戒細瀵艱嚧鑺卞睆銆傚彲浠ュ皾璇曞皢鎵鏈夊浘鍍忚漿鎹涓虹浉鍚岀殑鏍煎紡鍐嶈繘琛屽悎騫躲
4. 鍥懼儚澶勭悊綆楁硶闂棰橈細濡傛灉浣跨敤鐨勫浘鍍忓勭悊綆楁硶鍑虹幇闂棰橈紝鍙鑳戒細瀵艱嚧鑺卞睆銆傚彲浠ュ皾璇曚嬌鐢ㄥ叾浠栫畻娉曟垨鏌ユ壘宸茬煡鐨勯棶棰樹慨澶嶆柟娉曘
濡傛灉浠ヤ笂鏂規硶閮芥棤鏁堬紝鍙鑳介渶瑕佽繘涓姝ュ垎鏋愬浘鍍忓悎騫剁殑鍏蜂綋浠g爜鍜岀幆澧冭劇疆錛屾垨鑰呰冭檻鍚戠浉鍏蟲妧鏈璁哄潧鎴栫ぞ鍖哄繪眰甯鍔╋紝浠ヨ幏鍙栨洿鍏蜂綋鐨勮В鍐蟲柟妗堛
Ⅳ 怎麼給bitmap賦值 android
Bitmap是Android系統中的圖像處理的最重要的類之一。用它可以獲取圖像文件信息,對圖像進行旋轉,剪切,放大,縮小等操作。
Bitmap代表一張點陣圖,使我們在開發中常用的資源,下面就對Bitmap進行簡單的介紹。
Bitmap的獲取方法:
1、使用BitmapDrawable
BitmapDrawable里封裝的圖片就是一個Bitmap對象,我們要把Bitmap包裝成BitmapDrawable對象,可以調用BitmapDrawable的構造方法:
BItmapDrawbale drawable = new BItmapDrawable(bitmap);
如果要獲取BitmapDrawable所包裝的Bitmap對象,則可調用BitmapDrawable的getBitmap()方法:
Bitmap bitmap = drawbale.getBitmap();
2、Bitmap提供了一些靜態方法來創建Bitmap對象(僅列舉幾個):
createBitmap(Bitmap source,int x,int y,int width,int height):從原點陣圖source的指定坐標(x,y)開始,從中挖取寬width,高heigtht的一塊出來,創建新的Bitmap對象。
createScaledBitmap(Bitmap source,int width,ing height,boolean fliter):對源點陣圖進行縮放,縮放稱寬width,高heigth的新點陣圖。
createBitmap(int width,int height,Bitmap.Config config):創建一個寬width,高height的可變的新點陣圖。
createBitmap(Bitmap source, int x,int y,int width,int height ,Matrix m,boolean fliter):從源點陣圖source的指定坐標(x,y)開始,挖取寬width,高height的一塊來,創建新的Bitmap對象,並按照Matrix指定的規則進行變換。
3、通過對資源文件的解析獲取Bitmap對象
在這里就要用到BitmapFactory這個工具類,提供的方法如下:
decodeByteArray(byte[] data, int offset,int length):從指定位元組數組的offset位置開始,將長度為length的位元組數據解析成Bitmap對象。
decodeFIle(String pathName):從pathName指定的文件中解析、創建Bitmap對象。
decodeFileDescriptor(FileDescriptor fd):用於從FileDescriptor對應的文件中解析、創建Bitmap對象。
decodeResource(Resource res,int id):用於根據給定的資源ID從指定的資源文件中解析、創建Bitmap對象。
decodeStream(InputStream is):用於從指定輸入流中介解析、創建Bitmap對象。
但是,在系統不斷的解析、創建Bitmap的過程中,可能會由於內存小或其他原因,導致程序運行時發生OutOfMemory錯誤。
為此,Android為Bitmap提供了內存回收方法:
void recycle():強制回收Bitmap對象。
還有用於判斷Bitmap 對象是否被回收的方法:
boolean isRecycle();
如果Android應用需要訪問系統相冊,都需要藉助BitmapFactory解析、創建Bitmap對象。
4 從安卓無憂中看bitmap的幾種例子,下面是載入bitmap的例子,可以看裡面的源碼:
如果您對答案滿意,請您關注一下名字中微博。
Ⅵ Android 圖片載入(一)高效載入Bitmap 基礎篇
由於Bitmap的特殊性以及Android對單個應用所規定的最大內存限制,我們在同時載入大量Bitmap時很容易發生內存溢出,即我們通常所說的OutOfMemoryError(OOM),因此高效載入Bitmap就成為了每個Android開發者的必備技能。
在學習如何高效地載入Bitmap之前,首先介紹一下如何載入一個Bitmap。我們都知道,Bitmap在Android中通常指的是一張圖片,那麼如何將JPG、PNG等格式的圖片轉換成Bitmap對象呢?BitmapFactory類給我們提供了一些方法:
接下來開始介紹如何高效地載入Bitmap,其實核心思想很簡單: 就是採用BitmapFactory.Options參數來調整圖片尺寸來適配控制項的大小。
假如我們顯示圖片的控制項ImageView寬高為100×100像素,而圖片的尺寸為1024×1024像素,這個時候如果將整個圖片載入進來並顯示到控制項上,自然是很佔用內存資源的。這個時候可以通過BitmapFactory.Options按一定的采樣率載入縮小後的圖片,再將縮小後的圖片顯示到ImageView中,這樣就能減小內存佔用從而在一定程度上避免OOM的發生。
通過BitmapFactory.Options來縮放圖片,主要是使用它的inSampleSize參數,也就是前面提到的采樣率。當采樣率inSampleSize為1時,采樣後的圖片大小為原圖大小;當采樣率inSampleSize>1,比如為2時,采樣後的圖片寬高都為原圖的1/2,即像素降為原圖的1/4,佔用的內存大小也就是原圖的1/4;比較特殊的是,當采樣率inSampleSize<1時,系統會自動將該值當做1來處理。 因此可以得出一個結論:采樣率inSampleSize必須是大於1的整數圖片才會有縮小的效果,並且采樣率同時作用於寬高,也就是說采樣後的圖片會縮小到原圖的1/(inSampleSize^2)。比如inSampleSize=4,那麼縮放比例為1/16。
我們現在知道了,通過采樣率可以提高圖片的載入效率,那麼如何才能計算出最合適的采樣率?我們可以按照如下流程:
接下來以decodeFile方法為例實現圖片的縮放,其他三個方法處理方式類似。
下一篇: Android 圖片載入(二)圖片載入框架Glide 入門篇
《Android開發藝術探索》