Android加载大图片不OutOfMemoryError
Android加载图片时,对于分辨率小,配置低的机子,很容易发生OutOfMemoryError。手机的内存比图片的大很多,怎么会这样?在设置Android虚拟机的内存时:RAM:模拟器的内存空间VM Heap:dalvik虚拟机最大占用内存,也就是单个进程的最大占用内存。VM Heap高配的手机,可能有32M,64M,128M,而低配的手机,一般是16M,
·
Android加载图片时,对于分辨率小,配置低的机子,很容易发生OutOfMemoryError。手机的内存比图片的大很多,怎么会这样?
在设置Android虚拟机的内存时:
RAM:模拟器的内存空间
VM Heap:dalvik虚拟机最大占用内存,也就是单个进程的最大占用内存。
VM Heap高配的手机,可能有32M,64M,128M,而低配的手机,一般是16M,分辨率越大的手机,一般分配的也比较多。
Android系统对dalvik的vm heapsize作了硬性限制,当java进程申请的java空间超过阈值时,就会抛出OOM异常。也就是说RAM充足也会发生OOM的异常。
--------------------
VM Heap大小16mb,当应用加载一张大图时,加载图片所需要的内存空间不是按照图片大小算的,而是按照图片的像素点来算的。
图片像素点计算:
1张叫juhua.jsp的图片,大小1.27MB,分辨率:3840*2160,24位。
* Android保存图片像素信息,是用ARGB保存
* A:0-255,需要一个长度为8的二进制数字,占用1个字节
* R:0-255,需要一个长度为8的二进制数字,占用1个字节
* G:0-255,需要一个长度为8的二进制数字,占用1个字节
* B:0-255,需要一个长度为8的二进制数字,占用1个字节
3840*2160*4=33177600字节/1024/1024=31.640MB
超过了VM Heap的16MB,报内存溢出
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
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
************************************
解决方法:
按比例缩小图片,再加载。
现有手机屏幕分辨率 320*480
宽比:3840/320=12
高比:2160/480=4
选择比例大的数字12
缩放后再设置,就不会溢出了。
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" >
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点击加载大图片(OOO)"
android:onClick="loadPic"/>
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/btn1"
android:text="点击缩放加载大图片"
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 {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void loadPic(View v){
/*
* BitmapFactory.decodeResource(?,?)
* 这个带两个参数的方法:第一个参数是包含你要加载的位图资源文件的对象(一般写成 getResources()就ok了);
* 第二个时你需要加载的位图资源的Id。
BitmapFactory.decodeResource(?,?,?)带三个参数的方法:
前两个和上面的方法一样。第三个参数应该是对你要加载的位图是否需要完整显示,如果你只需要部分,可以在这里定制。
*/
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();
//默认为false,设为true,则decoder返回null,
//即BitmapFactory.decodeResource(getResources(),R.drawable.juhua,opts);返回null
//但会返回图片的参数的信息到Options对象里
//不解析图片到内存里
opts.inJustDecodeBounds=true;
BitmapFactory.decodeResource(getResources(),R.drawable.juhua,opts);
//获取图片的宽,高
int imageWidth=opts.outWidth;
int imageHeigth=opts.outHeight;
//获取屏幕的高宽
Display dp=getWindowManager().getDefaultDisplay();
//在高版本里有新的方法获取,但图片加载是常用功能,要兼容低版本,所以过时了也用
int screenWidth=dp.getWidth();
int screenHeight=dp.getHeight();
//计算缩放比例
int scale=1;
int scaleWidth=imageWidth/screenWidth;
int scaleHeight=imageHeigth/screenHeight;
//取缩放比例,取那个大的值
if(scaleWidth>=scaleHeight && scaleWidth>=1){
scale=scaleWidth;
}else if(scaleWidth<scaleHeight && scaleHeight>=1){
scale=scaleHeight;
}
//设置缩放比例
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);
}
}
更多推荐
已为社区贡献13条内容
所有评论(0)