Android加载大图片不OutOfMemoryError
Android加載圖片時(shí),對(duì)于分辨率小,配置低的機(jī)子,很容易發(fā)生OutOfMemoryError。手機(jī)的內(nèi)存比圖片的大很多,怎么會(huì)這樣?
在設(shè)置Android虛擬機(jī)的內(nèi)存時(shí):
RAM:模擬器的內(nèi)存空間
VM Heap:dalvik虛擬機(jī)最大占用內(nèi)存,也就是單個(gè)進(jìn)程的最大占用內(nèi)存。
VM Heap高配的手機(jī),可能有32M,64M,128M,而低配的手機(jī),一般是16M,分辨率越大的手機(jī),一般分配的也比較多。
Android系統(tǒng)對(duì)dalvik的vm heapsize作了硬性限制,當(dāng)java進(jìn)程申請(qǐng)的java空間超過閾值時(shí),就會(huì)拋出OOM異常。也就是說RAM充足也會(huì)發(fā)生OOM的異常。
--------------------
VM Heap大小16mb,當(dāng)應(yīng)用加載一張大圖時(shí),加載圖片所需要的內(nèi)存空間不是按照?qǐng)D片大小算的,而是按照?qǐng)D片的像素點(diǎn)來算的。
圖片像素點(diǎn)計(jì)算:
1張叫juhua.jsp的圖片,大小1.27MB,分辨率:3840*2160,24位。
* Android保存圖片像素信息,是用ARGB保存 ?* A:0-255,需要一個(gè)長度為8的二進(jìn)制數(shù)字,占用1個(gè)字節(jié)
?* R:0-255,需要一個(gè)長度為8的二進(jìn)制數(shù)字,占用1個(gè)字節(jié) ?* G:0-255,需要一個(gè)長度為8的二進(jìn)制數(shù)字,占用1個(gè)字節(jié) ?* B:0-255,需要一個(gè)長度為8的二進(jìn)制數(shù)字,占用1個(gè)字節(jié)
3840*2160*4=33177600字節(jié)/1024/1024=31.640MB 超過了VM Heap的16MB,報(bào)內(nèi)存溢出 10-27 06:16:27.645: I/dalvikvm-heap(1894): Forcing collection of SoftReferences for 33177612-byte allocation
10-27 06:16:27.645: E/dalvikvm-heap(1894): Out of memory on a 33177612-byte allocation.
10-27 06:16:27.655: E/AndroidRuntime(1894): Caused by: java.lang.OutOfMemoryError
************************************ 解決方法: 按比例縮小圖片,再加載。 現(xiàn)有手機(jī)屏幕分辨率 320*480 寬比:3840/320=12 高比:2160/480=4
選擇比例大的數(shù)字12
縮放后再設(shè)置,就不會(huì)溢出了。 31.640MB/12=2.64mb
代碼例子:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity" ><Buttonandroid:id="@+id/btn1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="點(diǎn)擊加載大圖片(OOO)"android:onClick="loadPic"/><Buttonandroid:id="@+id/btn2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@id/btn1"android:text="點(diǎn)擊縮放加載大圖片"android:onClick="scaleLoadPic"/><ImageView android:id="@+id/iv_pic"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@id/btn2"/></RelativeLayout>
package com.example.loadbigpic;import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapFactory.Options; import android.os.Bundle; import android.view.Display; import android.view.View; import android.widget.ImageView;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void loadPic(View v){/** BitmapFactory.decodeResource(?,?)* 這個(gè)帶兩個(gè)參數(shù)的方法:第一個(gè)參數(shù)是包含你要加載的位圖資源文件的對(duì)象(一般寫成 getResources()就ok了);* 第二個(gè)時(shí)你需要加載的位圖資源的Id。BitmapFactory.decodeResource(?,?,?)帶三個(gè)參數(shù)的方法:前兩個(gè)和上面的方法一樣。第三個(gè)參數(shù)應(yīng)該是對(duì)你要加載的位圖是否需要完整顯示,如果你只需要部分,可以在這里定制。*/Bitmap bm=BitmapFactory.decodeResource(getResources(),R.drawable.juhua);ImageView iv_pic=(ImageView) findViewById(R.id.iv_pic);iv_pic.setImageBitmap(bm);}public void scaleLoadPic(View v){Options opts=new Options();//默認(rèn)為false,設(shè)為true,則decoder返回null,//即BitmapFactory.decodeResource(getResources(),R.drawable.juhua,opts);返回null//但會(huì)返回圖片的參數(shù)的信息到Options對(duì)象里//不解析圖片到內(nèi)存里opts.inJustDecodeBounds=true;BitmapFactory.decodeResource(getResources(),R.drawable.juhua,opts);//獲取圖片的寬,高int imageWidth=opts.outWidth;int imageHeigth=opts.outHeight;//獲取屏幕的高寬Display dp=getWindowManager().getDefaultDisplay();//在高版本里有新的方法獲取,但圖片加載是常用功能,要兼容低版本,所以過時(shí)了也用int screenWidth=dp.getWidth();int screenHeight=dp.getHeight();//計(jì)算縮放比例int scale=1;int scaleWidth=imageWidth/screenWidth;int scaleHeight=imageHeigth/screenHeight;//取縮放比例,取那個(gè)大的值if(scaleWidth>=scaleHeight && scaleWidth>=1){scale=scaleWidth;}else if(scaleWidth<scaleHeight && scaleHeight>=1){scale=scaleHeight;}//設(shè)置縮放比例opts.inSampleSize=scale;opts.inJustDecodeBounds=false;Bitmap bm=BitmapFactory.decodeResource(getResources(),R.drawable.juhua,opts);ImageView iv_pic=(ImageView) findViewById(R.id.iv_pic);iv_pic.setImageBitmap(bm);}}
總結(jié)
以上是生活随笔為你收集整理的Android加载大图片不OutOfMemoryError的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mapreduce yarn内存参数
- 下一篇: Linux磁盘分区及要求