【Android】Bitmap最佳化

來源:互聯網
上載者:User

標籤:

Bitmap最佳化
  1. 一個進程的記憶體可以由2個部分組成:native和dalvik,dalvik就是我們平常說的java堆,我們建立的對象是在這裡面分配的,而bitmap是直 接在native上分配的。

    一旦記憶體配置給Java後,以後這塊記憶體即使釋放後,也只能給Java使用,所以如果Java突然佔用了一個大塊記憶體,即使很快釋放了,C能用的記憶體也是16M減去Java最大佔用的記憶體數。而Bitmap的產生是通過malloc進行記憶體配置的,佔用的是C的記憶體,這個也就說明了,假設13M記憶體被Java用過後,剩下C能用的只有3M了,所以如果有一個4M的Bitmap那肯定無法產生了。

  2. 在Android應用裡,最耗費記憶體的就是圖片資源。而且在Android系統中,讀取位元影像Bitmap時,分給虛擬機器中的圖片的堆棧大小隻有8M,如果超 出了,就會出現OutOfMemory異常。

  3. 及時回收Bitmap的記憶體

    // 先判斷是否已經回收if(bitmap != null && !bitmap.isRecycled()){    // 回收並且置為null    bitmap.recycle();    bitmap = null;}System.gc();
  4. 捕獲異常

    在執行個體化Bitmap的代碼中,一定要對OutOfMemory異常進行捕獲。下面對初始化Bitmap對象過程中可能發生的OutOfMemory異常進行了捕獲。如果發生了異常,應用不會崩潰,而是得到了一個預設的圖片。

    Bitmap bitmap = null;try {    // 執行個體化Bitmap    bitmap = BitmapFactory.decodeFile(path);} catch (OutOfMemoryError e) {//}if (bitmap == null) {    // 如果執行個體化失敗 返回預設的Bitmap對象    return defaultBitmapMap;}
  5. 緩衝通用的Bitmap對象

  6. 壓縮圖片

    如果圖片像素過大可以將圖片縮小,以減少載入圖片過程中的記憶體的使用,避免異常發生。
    使用BitmapFactory.Options.inSampleSize就可以縮小圖片。屬性值inSampleSize表示縮圖大小為原始圖片大小的幾分之一。即如果這個值為2,則取出的縮圖的寬和高都是原始圖片的1/2,圖片的大小就為原始大小的1/4。

    如果知道圖片的像素過大,就可以對其進行縮小。那麼如何才知道圖片過大呢?

    使用BitmapFactory.Options設定inJustDecodeBounds為true後,並不會真正的分配空間,即解碼出來的Bitmap為null,但是可計算出原始圖片的寬度和高度,即options.outWidth和options.outHeight。通過這兩個值,就可以知道圖片是否過大了。

    BitmapFactory.Options opts = new BitmapFactory.Options();// 設定inJustDecodeBounds為trueopts.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。

以從Gallery擷取一個圖片為例講解縮放:
public class MainActivity extends Activity {    private ImageView iv;    private WindowManager wm;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        wm = getWindowManager();        iv = (ImageView) findViewById(R.id.iv);    }    // 從系統的圖庫裡面 擷取一張照片    public void click(View view) {        Intent intent = new Intent();        intent.setAction("android.intent.action.PICK");        intent.addCategory("android.intent.category.DEFAULT");        intent.setType("image/*");        startActivityForResult(intent, 0);    }    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        if (data != null) {            // 擷取到系統圖庫返回回來圖片的uri            Uri uri = data.getData();            System.out.println(uri.toString());            try {                InputStream is = getContentResolver().openInputStream(uri);                // 1.計算出來螢幕的寬高.                int windowWidth = wm.getDefaultDisplay().getWidth();                int windowHeight = wm.getDefaultDisplay().getHeight();                //2. 計算圖片的寬高.                // 2.計算出來圖片的寬高.                BitmapFactory.Options opts = new Options();                // 設定 不去真正的解析位元影像 不把他載入到記憶體 只是擷取這個圖片的寬高資訊                opts.inJustDecodeBounds = true;                BitmapFactory.decodeStream(is, null, opts);                int bitmapHeight = opts.outHeight;                int bitmapWidth = opts.outWidth;                if (bitmapHeight > windowHeight || bitmapWidth > windowWidth) {                    int scaleX = bitmapWidth/windowWidth;                    int scaleY = bitmapHeight/windowHeight;                    if(scaleX>scaleY){//按照水平方向的比例縮放                        opts.inSampleSize = scaleX;                    }else{//按照豎直方向的比例縮放                        opts.inSampleSize = scaleY;                    }                }else{//如果圖片比手機螢幕小 不去縮放了.                    opts.inSampleSize = 1;                }                //讓位元影像工廠真正的去解析圖片                opts.inJustDecodeBounds = false;                //注意: 流的操作                is = getContentResolver().openInputStream(uri);                Bitmap bitmap = BitmapFactory.decodeStream(is, null, opts);                iv.setImageBitmap(bitmap);            } catch (Exception e) {                e.printStackTrace();        }        }        super.onActivityResult(requestCode, resultCode, data);    }}

歡迎androider關注公眾號:愛安卓

【Android】Bitmap最佳化

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.