這篇文章裡面只是想總結一下工作中使用bitmap遇到的一些使用情況。
bitmap翻譯過來就是"位圖",對於bitmap更多的優化問題吧!
bitmap類有乙個方法recycle(),從方法名可以看出是**的意思。雖然有gc,但是有時候**還是不盡如人意,這時候我們就需要用到recycle()我們手動來釋放bitmap的記憶體。
public void recycle()
mrecycled = true;
}}
boolean mrecycled:是否被**
使用了jni方法**bitmap,nativerecycle(mnativebitmap)的返回值表示原生畫素物件是否實際**。false表示它在native仍然在使用和這些物件現在不應該收集。當位圖本身被收集它們將被收集後。
一般來說,如果能夠獲得bitmap物件的引用,就需要及時的呼叫bitmap的recycle()方法來釋放bitmap占用的記憶體空間,而不要等android系統來進行釋放。
下面是釋放bitmap的示例**片段。
// 先判斷是否已經**
if(bitmap != null && !bitmap.isrecycled())
在bitmap不再需要的時候就可以進行**了
bitmap類的構造方法都是私有的,所以開發者不能直接new出乙個bitmap物件
一種是方式是使用bitmapfactory
先說用io流建立吧
inputstream is = res.openrawresource(r.drawable.welcome); // 讀取資源檔案獲取輸入流
//當然上面的io流也可以是網路獲取的,而bitmapfactory.options options的使用
bitmap bitmap = bitmapfactory.decodestream(is);//建立bitmap
但是當我們遇到一些大圖的時候就是出現oom了,所以bitmapfactory提供了另乙個方法
decodestream(inputstream is, rect outpadding, options opts)
這個options是bitmapfactory的乙個內部類,修改options的一些屬性可以幫助我們優化載入bitmap是的記憶體,示例**如下:
//例項化bitmapfactory.options
bitmapfactory.options options = new bitmapfactory.options();
options .inpreferredconfig = bitmap.config.rgb_565;
options .inpurgeable = true;
options .ininputshareable = true;
//建立bitmap
bitmap bitmap = bitmapfactory.decodestream(is, null, options);
其中inpreferredconfig是這是bitmap的每乙個畫素所佔的位的配置,而bitmap.config的配置有四種:
另外兩個屬性需要共同設定,inpurgeable和ininputshareable屬性我檢視過api但是沒有看的太明白,如果有明白的大神還請告訴一下。
還有一種是使用bitmap的createbitmap(),這個方法有一系列的方法都能夠建立bitmap,可能有人會很奇怪的問到為什麼會用到這個一系列的方法,那是在開發的時候遇到問題了,我需要根據scrollview的滑動去改變乙個圓角背景圖的顏色。可能大家都會去寫乙個drawable檔案來搞定圓角,但是顏色沒辦法動態改變啊!於是就想到自己去建立乙個bitmap,然後自己把它在切圓。找了一會找到這個方法bitmap.createbitmap
(int width, int height,
bitmap.config
config),可以生成乙個指定寬高的bitmap,後面的bitmap.config就是之前提到的位影象素位配置。
但是這樣得到的bitmap是乙個有寬高,沒有仍和顯示,因為還沒有個bitmap上的每乙個畫素設定顏色,那挨個畫素去設定這個想法應該不會有人去實現吧!於是就用用到的canvas(畫布)。
bitmap bitmap = bitmap.createbitmap(width,height,config.argb_4444);
canvas canvas = new canvas(bitmap);//構造乙個畫布來繪製bitmap
canvas.drawargb(255, 255, 255, 255);//設定繪製的顏色
canvas.drawbitmap(newb, 0, 0, null); //顯示在bitmap上
這樣bitmap就有顏色了,只差切圓角了;其實圓角可以在上面建立的那個過程就一併完成的,但是由於沒有自習學習沒有去合併**,這裡只是提供一中參考。
在上傳的時候使用過這個方法
bitmap的compress(compressformat format, int quality, outputstream stream)可以按指定的格式以及畫質,將轉換為輸出流。
format:bitmap.compressformat.png或bitmap.compressformat.jpeg
quality:畫質,0-100.0表示最低畫質壓縮,100以最高清壓縮。對於png等無損格式的,會忽略此項設定。
如果畫素過大,比如瀏覽**。可能我們就需要生成縮圖來優化,以減少載入過程中的記憶體的使用,避免發生outofmemory異常。
使用bitmapfactory.options中insamplesize就可以縮小。該屬性表示縮圖大小為原始大小的幾分之一。例如設定insamplesize=2,則取出的縮圖的寬和高都是原的1/2,的大小就為原圖大小的1/4。
我們可以預設對所有都進行這中處理,但是有些圖沒有必要進行壓縮形成縮圖的意義不大,還影響使用者體驗了。
於是我們可以通過設定bitmapfactory.options的injustdecodebounds=true之後,再使用上文中提到過的bitmapfactory.decodestream(is, null, options)等方法之後,我們就能在options中獲取到的原始寬高了,即options.outwidth和options.outheight。對這兩個值進行判斷就可以知道是否過大了。值得注意的是injustdecodebounds=true的時候執行decodestream方法並不會真正的分配空間,這時候獲取到的bitmap為null,所以這裡不用擔心會oom。
示例**:
bitmapfactory.options options= new bitmapfactory.options();
options.injustdecodebounds = true;// 設定injustdecodebounds為true
bitmapfactory.decodestream(is, null, options);// 使用decodefile方法得到的寬和高
int width = options.outwidth;
int height = options.outheight;
在實際專案中可以利用上面的**,先獲取真實的寬度和高度,然後判斷是否需要縮小。
如果不需要縮小,設定insamplesize的值為1。
如果需要縮小,則動態計算並設定insamplesize的值,對進行縮小。
這裡有一點需要注意,在下次使用bitmapfactory的decodestream()等方法例項化bitmap物件前,必須要將options.injustdecodebound設定為false,否則建立的bitmap為null。
為什麼這裡我舉例的是類似與相簿的使用呢?因為通過聯網獲取的我們可以在程式中進行壓縮和優化,同時服務端也可以根據不同的手機解析度返回不同的大小的來優化。
這是我在開發過程中遇到的一些問題肯定不是很全面,在這裡分享一下,有錯誤還請大家指正!!
還有一點值得說的是,即使已經優化的很好的,但是我們還是一定要捕獲exception或error,避免程式crash。
bitmap與2 bitmap使用總結
bitmap是一種簡單的資料結構,但在儲存空間壓縮方面卻使用廣泛。bitmap就是用乙個bit位來標記某個元素是否存在 1表示存在,0表示不存在 而2 bitmap就是用兩個bit為來標記某個元素出現的次數 00出現0次,01出現1次,10出現2次及其以上,11無意義。2 bitmap在記憶體中的表...
如何有效使用bitmap
使用bitmap容易遭遇out of memory exception,主要由以下三個原因 bitmap比較耗費記憶體,例如1300w畫素,每個畫素可能佔4個位元組 有些view group例如list view,grid view中可能包含很多bitmap。綜上,使用bitmap時主要考慮節省記憶...
使用Bitmap實現排序
使用bitmap實現排序,是通過在bitmap將待排序列表中的數值位標記為1,然後順序輸出bitmap的標記位實現排序的方法。具體來說,分為兩步 1 迴圈待排序列表,i 表示待排序列錶值。bitmap i 1 二 實踐篇 參考一篇python實現的bitmap encoding utf 8 auth...