不明白为什么 outOfMemory on setImageDrawable

Don't understand why OutOfMemory on setImageDrawable

我制作的自定义按钮控件有问题。 该按钮在布局中定义如下:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >

<ImageView
    android:layout_width="180dp"
    android:layout_height="180dp"
    android:layout_centerInParent="true"
    android:layout_margin="20dp"
    android:background="#fff"
    android:contentDescription="@string/my_button_info"
    android:src="@drawable/button_appearance" />

</merge>

和button_appearance是这样定义的:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/button_pic_down"
  android:state_pressed="true" />
<item android:drawable="@drawable/button_pic"
  android:state_focused="true" />
<item android:drawable="@drawable/button_pic" />
</selector>

现在,当我按下我的按钮(单击 LinearLayout)时,我将它显示为不同的位图并将其设置为旋转动画,这是动画:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1666"
android:fromDegrees="0"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:toDegrees="359" />

我这样称呼它:

public void animateButton() {
    myButton.setEnabled(false);
    myButton.setImageDrawable(getContext().getResources().getDrawable(R.drawable.button_pic_spin));
    myButton.startAnimation(AnimationUtils.loadAnimation(context, R.anim.spinner_animation));
}

然后,当它开始的动作完成时,我停止它:

public void stopAndEnableButton() {
    myButton.setEnabled(true);
    myButton.setImageDrawable(getContext().getResources().getDrawable(R.drawable.button_appearance));
    ttcButton.clearAnimation();
}

我在调用 setImageDrawable 的正上方的行中收到了 Crashlytics 的一些崩溃。 Crashlytics 说:

Failed to allocate a 2869648 byte allocation with 1275632 free bytes and 1245KB until OOM

奇怪的是,这里的 png 文件大小都在 25K 左右——而且只有 3 个(button_appearance.xml 中引用了 2 个,button_pic_spin 中引用了普通的 png)我们如何得到当我尝试交换最多应该只有 50K 的东西时需要 2 兆字节?

问题是应该先调用ClearAnimation再调用setImageDrawable吗?系统实际上是在尝试为部分旋转的位图进行大量分配吗?

您的图片太大,请尝试减小尺寸,或尝试使用第二个 post here 中的提示加载它。 (我说的是那些按钮图片)

如果您迫切需要解决方案,请在您的应用程序清单中提供 "largeHeap":true。

Android中图像的内存分配取决于图像的像素宽度和高度。不是磁盘大小。

Image Memory Size = width * height * 4 bytes (byte for red, byte for green, byte for blue and byte for alpha)

此错误由 Java 虚拟机 (JVM) 在由于内存不足 space 而无法分配对象时引发,而且垃圾收集器无法释放一些 space.

参考:

在清单文件中添加以下实体:android:hardwareAccelerated="false"android:largeHeap="true"

<application
android:allowBackup="true"
android:hardwareAccelerated="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
android:supportsRtl="true"
android:theme="@style/AppTheme">