Android BitmapFactory.decodeResource和无法解释的内存不足
我在解码可绘制图像资源960x926px jpg时遇到了一个奇怪的内存不足错误,分配了3555856字节。 图像仅放置在可绘制的xxhdpi(3x)中,我使用的是hdpi(1.5x)设备。 两个问题:Android BitmapFactory.decodeResource和无法解释的内存不足,android,android-image,android-bitmap,bitmapfactory,android-memory,Android,Android Image,Android Bitmap,Bitmapfactory,Android Memory,我在解码可绘制图像资源960x926px jpg时遇到了一个奇怪的内存不足错误,分配了3555856字节。 图像仅放置在可绘制的xxhdpi(3x)中,我使用的是hdpi(1.5x)设备。 两个问题: 为什么我在堆中有足够的空闲内存时会出错 hdpi设备的分配应为((960/2)x(926/2))x 4=888960字节(不是3555856字节) 有人能给我解释一下吗 注意:问题是为什么要为3.5MB分配一个OOM,而有22.5MB的可用内存(请参阅日志) 03-18 17:30:15.05
- 为什么我在堆中有足够的空闲内存时会出错
- hdpi设备的分配应为((960/2)x(926/2))x 4=888960字节(不是3555856字节)
3) 如果这导致OOM,则通常可能使用了太多内存。获得OOM的原因是,当图像解码到内存中时,其位图的大小大于图像分辨率(几乎是我不确定该值的4倍) 在处理图像时需要记住的几点:
Glide.with (context).load (path).asBitmap().into(imageView);
取自
步骤1:创建一个异步任务来解码位图
如果使用异步任务作为内部类,则考虑使用公共静态内部类(保存内存泄漏问题),并保持图像加载的IVIEVIEW的弱引用。还可以将要解码的图像资源、文件或流传递给构造函数。在下面的代码中,假设您想要解码资源。还包括步骤1中计算的焊道宽度和高度
public static class BitmapDecodeTask extends AsyncTask<Void, Void, Bitmap> {
//the reason to use a weak reference is to protect from memory leak issues.
private WeakReference<Context> mContextReference;
private WeakReference<ImageView> mImageViewReference;
private int mResourceId;
private int mRequiredWidth;
private int mRequiredHeight;
public BitmapDecodeTask(Context context, ImageView imageView, int resourceId, int width, int height) {
this.mContextReference = new WeakReference<>(context);
this.mImageViewReference = new WeakReference<>(imageView);
this.mResourceId = resourceId;
this.mRequiredWidth = width;
this.mRequiredHeight = height;
}
@Override
protected Bitmap doInBackground(Void... params) {
Context context = mContextReference.get();
if(context != null) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), mImageResourceId, options);
//set inSampleSize
options.inSampleSize = calculateInSampleSize(options);
//set inJustDecodeBounds = false;
options.inJustDecodeBounds = false;
//decode
return BitmapFactory.decodeResource(getResources(), mImageResourceId, options);
}
return null;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
//check if imageview is available or not
ImageView imageView = mImageViewReference.get();
if(imageView != null && bitmap != null) {
imageView.setImageBitmap(bitmap);
}
}
public static int calculateInSampleSize(BitmapFactory.Options options) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > mRequiredHeight || width > mRequiredWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > mRequiredHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
}
公共静态类BitmapDecodeTask扩展了AsyncTask{
//使用弱引用的原因是为了防止内存泄漏问题。
私人财富参照;
私有WeakReference mImageViewReference;
私有资源;
私有整数mRequiredWidth;
私人内部要求的高度;
公共位图解码任务(上下文上下文、ImageView、ImageView、int resourceId、int width、int height){
this.mContextReference=新的WeakReference(上下文);
this.mImageViewReference=新的WeakReference(imageView);
this.mResourceId=资源ID;
this.mRequiredWidth=宽度;
this.mRequiredHeight=高度;
}
@凌驾
受保护位图doInBackground(无效…参数){
Context=mContextReference.get();
if(上下文!=null){
BitmapFactory.Options=new-BitmapFactory.Options();
options.inJustDecodeBounds=true;
decodeResource(getResources(),mImageResourceId,选项);
//设置样本大小
options.inSampleSize=计算样本大小(选项);
//设置inJustDecodeBounds=false;
options.inJustDecodeBounds=false;
//解码
返回BitmapFactory.decodeResource(getResources(),mImageResourceId,options);
}
返回null;
}
@凌驾
受保护的void onPostExecute(位图){
//检查imageview是否可用
ImageView=mImageViewReference.get();
if(imageView!=null&&bitmap!=null){
设置图像位图(位图);
}
}
公共静态int-calculateInSampleSize(BitmapFactory.Options选项){
//图像的原始高度和宽度
最终内部高度=options.outHeight;
最终整数宽度=options.outWidth;
int inSampleSize=1;
如果(高度>mRequiredHeight | |宽度>mRequiredWidth){
最终int半高=高度/2;
最终整数半宽度=宽度/2;
//计算样本大小中的最大值
@Override
public void onDestroy() {
yourbitmap.recycle();
yourbitmap = null;
super.onDestroy();
}
compile 'com.github.bumptech.glide:glide:3.5.2'
Glide.with (context).load (path).asBitmap().into(imageView);