【问题标题】:imageSwitcher and memory errorsimageSwitcher 和内存错误
【发布时间】:2011-03-03 03:35:38
【问题描述】:

我正在使用非常简单的代码来显示存储为可绘制对象的图像库。所有图片的大小均小于 200kb,分辨率为 1024x576 像素。

我的代码在我测试过的 4 台设备上运行良好,并且适用于我的大多数用户。但是他们中的一些人不断遇到著名的虚拟机预算内存问题。

他是我的代码:

在我的活动的 onCreate() 方法中:

// set Factory for Image Switcher
imageSwitcher = (ImageSwitcher) findViewById(R.id.ImageSwitcher);
imageSwitcher.setFactory(new MyImageSwitcherFactory());

工厂类:

private class MyImageSwitcherFactory implements ViewFactory {
public View makeView() {
    ImageView imageView = new ImageView(Main.this);
    imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
    imageView.setLayoutParams(new ImageSwitcher.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
    return imageView;
}
}

以及显示图像的代码:

try {
    // this is internal image loaded from drawables
    imageSwitcher.setImageResource(images.get(imageNumber - 1).imageResourceID);

} catch (Exception e) {
    // no image will be shown
}

在 try/catch 块中的某些手机上发生错误(下载的百分比非常小),并且某些手机的活动甚至根本无法启动。

我阅读了有关回收位图和内存泄漏问题的信息,但我的活动在单顶模式下运行,并且不会在方向更改时重新创建,因此它始终是相同的活动。我也不直接使用位图。

我可以改进我的代码以消除这个错误吗?

第一种错误:

java.lang.OutOfMemoryError: bitmap size exceeds VM budget
    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:464)
    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:340)
    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
    at android.content.res.Resources.loadDrawable(Resources.java:1705)
    at android.content.res.Resources.getDrawable(Resources.java:580)
    at android.widget.ImageView.resolveUri(ImageView.java:548)
    at android.widget.ImageView.setImageResource(ImageView.java:270)
    at android.widget.ImageSwitcher.setImageResource(ImageSwitcher.java:41)
    at com.mobilebabytoys.animalsoundsfree.Main.showNextImage(Main.java:356)
    at com.mobilebabytoys.animalsoundsfree.Main.access$0(Main.java:284)
    at com.mobilebabytoys.animalsoundsfree.Main$MyGestureDetector.onFling(Main.java:861)
    at android.view.GestureDetector.onTouchEvent(GestureDetector.java:517)
    at com.mobilebabytoys.animalsoundsfree.Main$8.onTouch(Main.java:218)
    at android.view.View.dispatchTouchEvent(View.java:3705)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:874)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:924)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:924)
    at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1695)
    at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1116)
    at android.app.Activity.dispatchTouchEvent(Activity.java:2068)
    at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1679)
    at android.view.ViewRoot.handleMessage(ViewRoot.java:1697)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:4568)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:521)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
    at dalvik.system.NativeStart.main(Native Method)

第二种错误:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mobilebabytoys.animalsoundsfree/com.mobilebabytoys.animalsoundsfree.Main}: android.view.InflateException: Binary XML file line #15: Error inflating class <unknown>
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2596)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621)
    at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3812)
    at android.app.ActivityThread.access$2300(ActivityThread.java:126)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1936)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:4595)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:521)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: android.view.InflateException: Binary XML file line #15: Error inflating class <unknown>
    at android.view.LayoutInflater.createView(LayoutInflater.java:513)
    at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:563)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:618)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:407)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:207)
    at android.app.Activity.setContentView(Activity.java:1629)
    at com.mobilebabytoys.animalsoundsfree.Main.onCreate(Main.java:154)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2544)
    ... 12 more
Caused by: java.lang.reflect.InvocationTargetException
    at android.widget.ImageButton.<init>(ImageButton.java:78)
    at java.lang.reflect.Constructor.constructNative(Native Method)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:446)
    at android.view.LayoutInflater.createView(LayoutInflater.java:500)
    ... 23 more
Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:464)
    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:340)
    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
    at android.content.res.Resources.loadDrawable(Resources.java:1705)
    at android.content.res.Resources.getDrawable(Resources.java:580)
    at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:160)
    at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:788)
    at android.graphics.drawable.Drawable.createFromXml(Drawable.java:729)
    at android.content.res.Resources.loadDrawable(Resources.java:1690)
    at android.content.res.TypedArray.getDrawable(TypedArray.java:548)
    at android.widget.ImageView.<init>(ImageView.java:115)
    at android.widget.ImageButton.<init>(ImageButton.java:82)
    ... 27 more
android.view.InflateException: Binary XML file line #15: Error inflating class <unknown>
    at android.view.LayoutInflater.createView(LayoutInflater.java:513)
    at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:563)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:618)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:407)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:207)
    at android.app.Activity.setContentView(Activity.java:1629)
    at com.mobilebabytoys.animalsoundsfree.Main.onCreate(Main.java:154)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2544)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621)
    at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3812)
    at android.app.ActivityThread.access$2300(ActivityThread.java:126)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1936)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:4595)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:521)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.reflect.InvocationTargetException
    at android.widget.ImageButton.<init>(ImageButton.java:78)
    at java.lang.reflect.Constructor.constructNative(Native Method)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:446)
    at android.view.LayoutInflater.createView(LayoutInflater.java:500)
    ... 23 more
Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:464)
    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:340)
    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
    at android.content.res.Resources.loadDrawable(Resources.java:1705)
    at android.content.res.Resources.getDrawable(Resources.java:580)
    at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:160)
    at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:788)
    at android.graphics.drawable.Drawable.createFromXml(Drawable.java:729)
    at android.content.res.Resources.loadDrawable(Resources.java:1690)
    at android.content.res.TypedArray.getDrawable(TypedArray.java:548)
    at android.widget.ImageView.<init>(ImageView.java:115)
    at android.widget.ImageButton.<init>(ImageButton.java:82)
    ... 27 more
java.lang.reflect.InvocationTargetException
    at android.widget.ImageButton.<init>(ImageButton.java:78)
    at java.lang.reflect.Constructor.constructNative(Native Method)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:446)
    at android.view.LayoutInflater.createView(LayoutInflater.java:500)
    at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:563)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:618)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:407)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:207)
    at android.app.Activity.setContentView(Activity.java:1629)
    at com.mobilebabytoys.animalsoundsfree.Main.onCreate(Main.java:154)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2544)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621)
    at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3812)
    at android.app.ActivityThread.access$2300(ActivityThread.java:126)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1936)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:4595)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:521)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:464)
    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:340)
    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
    at android.content.res.Resources.loadDrawable(Resources.java:1705)
    at android.content.res.Resources.getDrawable(Resources.java:580)
    at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:160)
    at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:788)
    at android.graphics.drawable.Drawable.createFromXml(Drawable.java:729)
    at android.content.res.Resources.loadDrawable(Resources.java:1690)
    at android.content.res.TypedArray.getDrawable(TypedArray.java:548)
    at android.widget.ImageView.<init>(ImageView.java:115)
    at android.widget.ImageButton.<init>(ImageButton.java:82)
    ... 27 more
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:464)
    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:340)
    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
    at android.content.res.Resources.loadDrawable(Resources.java:1705)
    at android.content.res.Resources.getDrawable(Resources.java:580)
    at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:160)
    at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:788)
    at android.graphics.drawable.Drawable.createFromXml(Drawable.java:729)
    at android.content.res.Resources.loadDrawable(Resources.java:1690)
    at android.content.res.TypedArray.getDrawable(TypedArray.java:548)
    at android.widget.ImageView.<init>(ImageView.java:115)
    at android.widget.ImageButton.<init>(ImageButton.java:82)
    at android.widget.ImageButton.<init>(ImageButton.java:78)
    at java.lang.reflect.Constructor.constructNative(Native Method)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:446)
    at android.view.LayoutInflater.createView(LayoutInflater.java:500)
    at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:563)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:618)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:407)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:207)
    at android.app.Activity.setContentView(Activity.java:1629)
    at com.mobilebabytoys.animalsoundsfree.Main.onCreate(Main.java:154)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2544)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621)
    at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3812)
    at android.app.ActivityThread.access$2300(ActivityThread.java:126)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1936)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:4595)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:521)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
    at dalvik.system.NativeStart.main(Native Method)

我的活动布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/MainLayout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:keepScreenOn="true">
    <ImageSwitcher
        android:keepScreenOn="true"
        android:id="@+id/ImageSwitcher"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    </ImageSwitcher>

</RelativeLayout>

【问题讨论】:

    标签: android image memory


    【解决方案1】:

    关于位图错误:
    您应该考虑对位图进行下采样并在内存中创建它们之前调整它们的大小。看看下面的线程Handling Large Bitmaps

    第二个错误是导致运行时无法从布局 XML 创建视图层次结构。您是否在布局中使用自定义视图?

    编辑:您的布局 XML 看起来正确,现在您已经发布了整个转储,对我来说唯一的问题是位图的大小。我仍然认为您将不得不对图像进行下采样。

    您的图片格式是什么;解压缩为Bitmap 时,1024 x 576 JPEG 图像可能太大。

    看看这些讨论中是否有任何指示:123

    【讨论】:

    • 感谢您的回答,但我认为不需要缩小 - 图片小于 200kb,应该没问题。除了缩小规模不是免费的 - 这需要时间。第二个错误也是“引起:java.lang.OutOfMemoryError:位图大小超过 VM 预算”。我不对该活动使用自定义视图
    • 您能否再次查看日志并检查 VM 是否尝试了 200kb 分配,还是超过了这个?
    • 已完成,希望对您有所帮助。我也玩过内存分析器,在我的图片上疯狂点击了几分钟后,我没有发现任何泄漏。我什至无法在我尝试过的 4 台设备和模拟器上重现这些错误。
    • 是的,但是您确实意识到,无论您喜欢与否,图像已经被缩小,因为每次加载它(假设您的设备的屏幕
    • @mishkin 您的图片已压缩 200KB。当解压到 RAM 中时,如果使用 32bpp 位图(超过 2MB!),它们将约为 2200KB,如果使用 16bpp,则为 2200KB。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-29
    • 1970-01-01
    相关资源
    最近更新 更多