图像太大:OutOfMemory异常

时间:2014-01-10 15:09:49

标签: java android image user-interface android-fragments

我的背景图片太大,因此应用程序崩溃时出现以下错误(我正在从LogCat复制其他有用的消息)

01-10 14:53:48.799: E/dalvikvm-heap(9297): Out of memory on a 6955024-byte allocation.
01-10 14:53:48.799: I/dalvikvm(9297): "main" prio=5 tid=1 RUNNABLE
01-10 14:53:48.799: I/dalvikvm(9297):   | group="main" sCount=0 dsCount=0 obj=0x40a729a0 self=0x2a00bba8
01-10 14:53:48.799: I/dalvikvm(9297):   | sysTid=9297 nice=0 sched=0/0 cgrp=apps handle=1073849308
01-10 14:53:48.812: I/dalvikvm(9297):   | state=R schedstat=( 38497557466 45560972992 4658 ) utm=3335 stm=514 core=0
01-10 14:53:48.840: I/dalvikvm(9297):   at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
01-10 14:53:48.840: I/dalvikvm(9297):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:502)
01-10 14:53:48.840: I/dalvikvm(9297):   at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:355)
01-10 14:53:48.840: I/dalvikvm(9297):   at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:785)
01-10 14:53:48.840: I/dalvikvm(9297):   at android.content.res.Resources.loadDrawable(Resources.java:1965)
01-10 14:53:48.840: I/dalvikvm(9297):   at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
01-10 14:53:48.840: I/dalvikvm(9297):   at android.view.View.<init>(View.java:3330)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.view.View.<init>(View.java:3259)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.view.ViewGroup.<init>(ViewGroup.java:425)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.widget.RelativeLayout.<init>(RelativeLayout.java:210)
01-10 14:53:48.860: I/dalvikvm(9297):   at java.lang.reflect.Constructor.constructNative(Native Method)
01-10 14:53:48.860: I/dalvikvm(9297):   at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.view.LayoutInflater.createView(LayoutInflater.java:587)
01-10 14:53:48.860: I/dalvikvm(9297):   at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.view.LayoutInflater.onCreateView(LayoutInflater.java:660)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.view.LayoutInflater.inflate(LayoutInflater.java:466)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
01-10 14:53:48.860: I/dalvikvm(9297):   at com.xxx.xxx.InputFragment.onCreateView(InputFragment.java:70)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.support.v4.app.Fragment.performCreateView(Fragment.java:1478)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:927)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1086)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1877)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:552)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1164)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.app.Activity.performStart(Activity.java:5114)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2153)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3692)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.app.ActivityThread.access$700(ActivityThread.java:141)
01-10 14:53:48.860: I/dalvikvm(9297):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1240)
01-10 14:53:48.910: I/dalvikvm(9297):   at android.os.Handler.dispatchMessage(Handler.java:99)
01-10 14:53:48.910: I/dalvikvm(9297):   at android.os.Looper.loop(Looper.java:137)
01-10 14:53:48.920: I/dalvikvm(9297):   at android.app.ActivityThread.main(ActivityThread.java:5041)
01-10 14:53:48.920: I/dalvikvm(9297):   at java.lang.reflect.Method.invokeNative(Native Method)
01-10 14:53:48.920: I/dalvikvm(9297):   at java.lang.reflect.Method.invoke(Method.java:511)
01-10 14:53:48.920: I/dalvikvm(9297):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
01-10 14:53:48.920: I/dalvikvm(9297):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
01-10 14:53:48.920: I/dalvikvm(9297):   at dalvik.system.NativeStart.main(Native Method)
01-10 14:53:49.315: D/skia(9297): --- decoder->decode returned false
01-10 14:53:49.315: D/AndroidRuntime(9297): Shutting down VM
01-10 14:53:49.320: W/dalvikvm(9297): threadid=1: thread exiting with uncaught exception (group=0x40a71930)
01-10 14:53:49.570: E/AndroidRuntime(9297): FATAL EXCEPTION: main
01-10 14:53:49.570: E/AndroidRuntime(9297): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.xxx.xxx/com.xxx.xxx.MainActivity}: android.view.InflateException: Binary XML file line #1: Error inflating class <unknown>
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3692)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.app.ActivityThread.access$700(ActivityThread.java:141)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1240)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.os.Looper.loop(Looper.java:137)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.app.ActivityThread.main(ActivityThread.java:5041)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at java.lang.reflect.Method.invokeNative(Native Method)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at java.lang.reflect.Method.invoke(Method.java:511)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at dalvik.system.NativeStart.main(Native Method)
01-10 14:53:49.570: E/AndroidRuntime(9297): Caused by: android.view.InflateException: Binary XML file line #1: Error inflating class <unknown>
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.view.LayoutInflater.createView(LayoutInflater.java:613)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.view.LayoutInflater.onCreateView(LayoutInflater.java:660)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.view.LayoutInflater.inflate(LayoutInflater.java:466)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at com.xxx.xxx.InputFragment.onCreateView(InputFragment.java:70)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.support.v4.app.Fragment.performCreateView(Fragment.java:1478)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:927)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1086)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1877)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:552)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1164)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.app.Activity.performStart(Activity.java:5114)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2153)
01-10 14:53:49.570: E/AndroidRuntime(9297):     ... 12 more
01-10 14:53:49.570: E/AndroidRuntime(9297): Caused by: java.lang.reflect.InvocationTargetException
01-10 14:53:49.570: E/AndroidRuntime(9297):     at java.lang.reflect.Constructor.constructNative(Native Method)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.view.LayoutInflater.createView(LayoutInflater.java:587)
01-10 14:53:49.570: E/AndroidRuntime(9297):     ... 27 more
01-10 14:53:49.570: E/AndroidRuntime(9297): Caused by: java.lang.OutOfMemoryError
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:502)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:355)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:785)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.content.res.Resources.loadDrawable(Resources.java:1965)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.view.View.<init>(View.java:3330)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.view.View.<init>(View.java:3259)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.view.ViewGroup.<init>(ViewGroup.java:425)
01-10 14:53:49.570: E/AndroidRuntime(9297):     at android.widget.RelativeLayout.<init>(RelativeLayout.java:210)
01-10 14:53:49.570: E/AndroidRuntime(9297):     ... 30 more

我的背景图片位于Drawable文件夹中。是的,我的意思是“文件夹”,因为该应用程序旨在支持多个屏幕,图像位于所有文件夹中,只是略有变化。

如何在没有问题的情况下加载这些大位图?我查看了以下代码。

public static Bitmap getResizedBitmap(Bitmap image, int newHeight, int newWidth) {
    int width = image.getWidth();
    int height = image.getHeight();
    float scaleWidth = ((float) newWidth) / width;
    float scaleHeight = ((float) newHeight) / height;
    // create a matrix for the manipulation
    Matrix matrix = new Matrix();
    // resize the bit map
    matrix.postScale(scaleWidth, scaleHeight);
    // recreate the new Bitmap
    Bitmap resizedBitmap = Bitmap.createBitmap(image, 0, 0, width, height,
            matrix, false);
    return resizedBitmap;
}

但情况是,这段代码手动设置宽度和高度,对吧?但我打算将此图像应用为背景图像,所以我不知道这是否是最好的方法,而且我不确定要插入宽度和高度的值。我所知道的是我需要用onCreateView()方法设置图像(我正在使用片段)。

2 个答案:

答案 0 :(得分:1)

使用BitmapFactory.Options在加载图像之前获取图像的大小,然后您可以将背景缩小到较低分辨率的图像(如果需要),它仍然适合背景但不会引发OOM错误。此外,您可以使用DisplayMetrics获取所需的宽度和高度,或者您正在设置背景的视图的宽度和高度。

来自android培训文档(http://developer.android.com/training/displaying-bitmaps/load-bitmap.html):

  

BitmapFactory类提供了几种解码方法   (decodeByteArray(),decodeFile(),decodeResource()等)用于创建   来自各种来源的位图。选择最合适的解码   基于图像数据源的方法。这些方法试图   为构造的位图分配内存,因此很容易   导致OutOfMemory异常。每种类型的解码方法都有   允许您通过指定解码选项的其他签名   BitmapFactory.Options类。设置inJustDecodeBounds属性   解码时为true,避免内存分配,返回null   位图对象但设置outWidth,outHeight和outMimeType。   此技术允许您读取图像的尺寸和类型   位图构造(和内存分配)之前的数据。

 BitmapFactory.Options options = new BitmapFactory.Options();
 options.inJustDecodeBounds = true;
 BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
 int imageHeight = options.outHeight; 
 int imageWidth = options.outWidth; 
 String imageType = options.outMimeType;
  

要避免java.lang.OutOfMemory异常,请检查a的维度   解码之前的位图,除非你绝对信任源   为您提供可预测的大小适合的图像数据   在可用的记忆中。

答案 1 :(得分:0)

您需要为JVM(-Xmx7g)分配更多堆,或者平铺图像,这样您就不需要立即将整个内容保存在内存中。
 如果您没有一次显示整个图像,则平铺仅在当然有用。如果您要管理它,您可以在尝试加载之前以某种方式压缩图像 还有第三方库,例如DiscMemImage,可以在限制内存使用的同时使用图像。