android - imageSwitcher 和内存错误

标签 android image memory

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

我的代码在我测试的 4 台设备上运行良好,并且适用于我的大多数用户。但是其中一些不断出现著名的 vm 预算内存问题。

他是我的代码:

在我的 Activity 的 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 block 中发生错误,并且某些手机的 Activity 甚至根本无法启动。

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

我能否以某种方式改进我的代码以消除此错误?

第一类错误:

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)

我的 Activity 布局:

<?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>

最佳答案

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

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

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

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

查看这些讨论中是否有任何指示:1 , 2 , 3 .

关于android - imageSwitcher 和内存错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5176367/

相关文章:

android - 如何获取 ViewModel?

image - codeigniter 图像路径

PHP - 猜测变量中存储的图像的 MIME 类型

c++ - C 中位域的内存布局 - 无法理解输出

python - Python 函数调用后是否仍然使用内存?

android - 在 FragmentView Kotlin 中获取上下文的问题

android - Xamarin Android 应用程序名称未设置

javascript - Android CSS spritesheet webkit 转换和动画的问题

image - 如果图像是链接,如何从拖放中获取图像 URL?

我们可以通过 mmap() 分配物理上连续的内存吗?