Android OutOfMemoryError:?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21012006/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android OutOfMemoryError:?
提问by NagarjunaReddy
I am sporadically getting an OutOfMemoryError: (Heap Size=49187KB, Allocated=41957KB)
in one of my apps. What can I do to diagnose this?
我偶尔会OutOfMemoryError: (Heap Size=49187KB, Allocated=41957KB)
在我的一个应用程序中获得一个。我该怎么做才能诊断出这种情况?
01-09 10:32:02.079: E/dalvikvm(8077): Out of memory: Heap Size=49187KB, Allocated=41957KB, Limit=49152KB
01-09 10:32:02.079: E/dalvikvm(8077): Extra info: Footprint=48611KB, Allowed Footprint=49187KB, Trimmed=7852KB
01-09 10:32:02.079: D/skia(8077): --- decoder->decode returned false
01-09 10:32:02.079: D/AndroidRuntime(8077): Shutting down VM
01-09 10:32:02.079: W/dalvikvm(8077): threadid=1: thread exiting with uncaught exception (group=0x40a97228)
01-09 10:32:02.079: E/AndroidRuntime(8077): FATAL EXCEPTION: main
01-09 10:32:02.079: E/AndroidRuntime(8077): java.lang.OutOfMemoryError: (Heap Size=49187KB, Allocated=41957KB)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:486)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:773)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.content.res.Resources.loadDrawable(Resources.java:2044)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.content.res.Resources.getDrawable(Resources.java:675)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.view.View.setBackgroundResource(View.java:11776)
01-09 10:32:02.079: E/AndroidRuntime(8077): at com.blsk.bigtoss.ImageLoader.DisplayImage(ImageLoader.java:81)
01-09 10:32:02.079: E/AndroidRuntime(8077): at com.blsk.bigtoss.MatchActivity$MatchAsyncTask.onPostExecute(MatchActivity.java:1768)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.os.AsyncTask.finish(AsyncTask.java:602)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.os.AsyncTask.access0(AsyncTask.java:156)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:615)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.os.Handler.dispatchMessage(Handler.java:99)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.os.Looper.loop(Looper.java:156)
01-09 10:32:02.079: E/AndroidRuntime(8077): at android.app.ActivityThread.main(ActivityThread.java:4987)
01-09 10:32:02.079: E/AndroidRuntime(8077): at java.lang.reflect.Method.invokeNative(Native Method)
01-09 10:32:02.079: E/AndroidRuntime(8077): at java.lang.reflect.Method.invoke(Method.java:511)
01-09 10:32:02.079: E/AndroidRuntime(8077): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
01-09 10:32:02.079: E/AndroidRuntime(8077): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
01-09 10:32:02.079: E/AndroidRuntime(8077): at dalvik.system.NativeStart.main(Native Method)
01-09 10:32:02.099: E/EmbeddedLogger(1612): App crashed! Process: com.blsk.bigtoss
01-09 10:32:02.099: E/EmbeddedLogger(1612): App crashed! Package: com.blsk.bigtoss v6 (1.2)
01-09 10:32:02.129: E/EmbeddedLogger(1612): Application Label: Cricket
This is the line where it is happening:
这是发生的行:
LinearLayout resultMatchHeaderContainer = new LinearLayout(activity);
if (!resultImagePath.equals("")) {
imageLoader.DisplayImage(resultImagePath,resultMatchHeaderContainer, -1,modifiedHeight, R.drawable.matches_placeholder_result2x);
} else {
try {
resultMatchHeaderContainer.setBackgroundResource(R.drawable.matches_placeholder_result2x);
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
}
回答by SKULL
maybe this help you ?
也许这对你有帮助?
add manifest
添加清单
android > v3
安卓 > v3
<application
....
android:largeHeap="true">
回答by CommonSenseCode
Common fixes:
常见修复:
1. Fix your contexts:
1. 修正你的上下文:
Try using the appropiate context: For example since a Toast can be seen in many activities instead of in just one, use getApplicationContext()
for toasts, and since services can keep running even though an activity has ended start a service with:
尝试使用适当的上下文:例如,由于 Toast 可以在许多活动中看到,而不是仅在一个活动中看到,因此getApplicationContext()
用于吐司,并且由于即使活动已结束,服务仍可以继续运行,因此可以使用以下方式启动服务:
Intent myService = new Intent(getApplicationContext(), MyService.class)
Intent myService = new Intent(getApplicationContext(), MyService.class)
Use this table as a quick guide for what context is appropiate:
Original article on context here.
2. Check that you're actually finishing your services.
2. 检查您是否真的完成了您的服务。
For example I have an intentService that use google location service api. And I forgot to call googleApiClient.disconnect();
:
例如,我有一个使用 google 位置服务 api 的 intentService。我忘了打电话googleApiClient.disconnect();
:
//Disconnect from API onDestroy()
if (googleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, GoogleLocationService.this);
googleApiClient.disconnect();
}
3. Check image and bitmaps usage:
3. 检查图像和位图使用情况:
If you are using square's library PicassoI found I was leaking memory by not using the .fit()
, that drastically reduced my memory footprint from 50MB in average to less than 19MB:
如果您使用 square 的库 Picasso,我发现我不使用 会导致内存泄漏.fit()
,这大大减少了我的内存占用,从平均 50MB 减少到不到 19MB:
Picasso.with(ActivityExample.this) //Activity context
.load(object.getImageUrl())
.fit() //This avoided the OutOfMemoryError
.centerCrop() //makes image to not stretch
.into(imageView);
4. If you are using broadcast receivers unregister them.
4. 如果您正在使用广播接收器,请取消注册它们。
5. If you are using java.util.Observer
(Observer pattern):
5. 如果你使用java.util.Observer
(观察者模式):
Make sure to to use deleteObserver(observer);
确保使用 deleteObserver(observer);
回答by Avtar Guleria
You can do following to avoid this.
您可以执行以下操作来避免这种情况。
Drawable drawable = resultMatchHeaderContainer.getDrawable();
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
if (bitmapDrawable != null) {
Bitmap bitmap = bitmapDrawable.getBitmap();
if (bitmap != null && !bitmap.isRecycled())
bitmap.recycle();
}
}
Loading Bitmap in Imageview always been a cause of out of memory issue it is very common so we have to handle imageview and bitmaps very carefully. What you can do is While setting any background bitmap to your imageview first get the drawable and recycle it so that it is removed from memory and then set the new bitmap. This will help to avoid any OOM issue. Further. You can use BitmapFactoryOptions to reduce the size of your bitmap. like:
在 Imageview 中加载 Bitmap 一直是内存不足问题的一个原因,这是很常见的,所以我们必须非常小心地处理 imageview 和位图。您可以做的是在将任何背景位图设置到您的图像视图时,首先获取可绘制对象并回收它,以便将其从内存中删除,然后设置新的位图。这将有助于避免任何 OOM 问题。更远。您可以使用 BitmapFactoryOptions 来减小位图的大小。喜欢:
// decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f) {
try {
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream stream1 = new FileInputStream(f);
BitmapFactory.decodeStream(stream1, null, o);
stream1.close();
// Find the correct scale value. It should be the power of 2.
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < REQUIRED_WIDTH
|| height_tmp / 2 < REQUIRED_HIGHT)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
FileInputStream stream2 = new FileInputStream(f);
Bitmap bitmap = BitmapFactory.decodeStream(stream2, null, o2);
stream2.close();
return bitmap;
} catch (FileNotFoundException e) {
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
回答by dipali
final Bitmap smile = BitmapFactory.decodeResource(getResources(), R.drawable.emo_im_happy);
最终位图微笑 = BitmapFactory.decodeResource(getResources(), R.drawable.emo_im_happy);
Call
称呼
String pathname=BitMapToString(smile);
String pathname=BitMapToString(smile);
and then call
然后打电话
setImagesNew(linearview,pathname,activity);
...
...
public String BitMapToString(Bitmap bitmap) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
String temp = Base64.encodeToString(b, Base64.DEFAULT);
return temp;
}
public static void setImagesNew(LinearLayout linearLayout, String pathName,
Activity activity) {
Bitmap bmp = decodeSampledBitmapFromResource(pathName,
getDeviceWidth(activity), getDeviceHeight(activity));
linearLayout.setBackgroundDrawable(bmp);
bmp = null;
System.gc();
Runtime.getRuntime().gc();
}
public static Bitmap decodeSampledBitmapFromResource(String pathName,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathName, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(pathName, options);
}
public static int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
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) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
@SuppressLint("NewApi")
public static int getDeviceWidth(Activity activity) {
int deviceWidth = 0;
Point size = new Point();
WindowManager windowManager = activity.getWindowManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
windowManager.getDefaultDisplay().getSize(size);
deviceWidth = size.x;
} else {
Display display = windowManager.getDefaultDisplay();
deviceWidth = display.getWidth();
}
return deviceWidth;
}
@SuppressLint("NewApi")
public static int getDeviceHeight(Activity activity) {
int deviceHeight = 0;
Point size = new Point();
WindowManager windowManager = activity.getWindowManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
windowManager.getDefaultDisplay().getSize(size);
deviceHeight = size.y;
} else {
Display display = windowManager.getDefaultDisplay();
deviceHeight = display.getHeight();
}
return deviceHeight;
}
please put all function in your activity and call only setImageNew()
and pass parameter in imageview ,sdcardpathname and activity
请将所有函数放在您的活动中,并仅setImageNew()
在 imageview、sdcardpathname 和活动中调用和传递参数
I hope it will not crash after you implement this code. because I arise same problem as you..
我希望在您实现此代码后它不会崩溃。因为我遇到和你一样的问题..
回答by Magnus
This could occur for several reasons, you might be keeping references to other parts of your code too long. You might be loading to large bitmaps which together with holding on to many referencesgives you OOM, etc.
这可能有多种原因,您可能会将对代码其他部分的引用保留太长时间。您可能正在加载大型位图,这些位图与保留许多引用一起会给您带来 OOM 等。
Normally when an OOM occurs a hprof(snapshot of the Heap) is created on the root of the sdcard (or internal storage if sdcard does not exist), which can be read by tools like Eclipse MAT(included in the android tools if you use Eclipse). First one might need to convert the hprof with hprof-conv
tool. Here's one tutorial of how to use Eclipse MAT: Investigating Your RAM Usage. The leak suspects report is a good first read when hprof is loaded in Eclipse MAT
通常,当发生 OOM 时,会在 sdcard 的根目录(如果 sdcard 不存在,则为内部存储)创建hprof(堆快照),可以通过Eclipse MAT等工具读取(如果您使用,则包含在 android 工具中)蚀)。第一个可能需要使用hprof-conv
工具转换 hprof 。这是有关如何使用 Eclipse MAT 的一个教程:调查您的 RAM 使用情况。当在 Eclipse MAT 中加载 hprof 时,泄漏嫌疑人报告是一个很好的第一次阅读
After profiling you you could read up on how to load images effectively from Displaying Bitmaps Efficiently
在分析之后,您可以阅读如何从有效地显示位图有效地加载图像
There's also several popular image loading libraries such as universal image loaderand picassoavailable, that do what you need with ease.
回答by rajahsekar
Before loading images into memory compress your images using
在将图像加载到内存之前,使用压缩图像
Bitmap original = BitmapFactory.decodeStream(getAssets().open("1024x768.jpg"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
original.compress(Bitmap.CompressFormat.PNG, 100, out);
Bitmap decoded = BitmapFactory.decodeStream(new ByteArrayInputStream(out.toByteArray()));
Log.e("Original dimensions", original.getWidth()+" "+original.getHeight());
Log.e("Compressed dimensions", decoded.getWidth()+" "+decoded.getHeight());
If you are geting your bitmap from a resource, in which case the bitmap dimension will depend on the phone screen density
如果您从资源中获取位图,在这种情况下,位图尺寸将取决于手机屏幕密度
Bitmap bitmap=((BitmapDrawable)getResources().getDrawable(R.drawable.img_1024x768)).getBitmap();
Log.e("Dimensions", bitmap.getWidth()+" "+bitmap.getHeight());
回答by Selvan
This may happen if the bitmap resource is not disposed correctly. It is better to read the dimensions to see if it fits the memory. http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
如果位图资源未正确处理,则可能会发生这种情况。最好是读取尺寸,看是否适合内存。 http://developer.android.com/training/displaying-bitmaps/load-bitmap.html