【问题标题】:How to change between sprite action animations seamlessly without running into OOM?如何在不遇到OOM的情况下无缝切换精灵动作动画?
【发布时间】:2023-03-31 23:14:01
【问题描述】:

我有精灵动画,例如跑步、睡觉、走路、跳跃等。这些动画中的每一个都可以自己工作,但是当我尝试使用 setBackgroundResource() 将动画更改为不同的动画集时,我遇到了内存问题,而前一个动画处于活动状态。我相信以前的动画集没有从内存中清除。可以做些什么来避免内存问题?

内存错误:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.app.debug, PID: 5668
java.lang.OutOfMemoryError: Failed to allocate a 5644812 byte allocation with 1290256 free bytes and 1260KB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:856)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:675)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:2228)
at android.content.res.Resources.loadDrawableForCookie(Resources.java:4215)
at android.content.res.Resources.loadDrawable(Resources.java:4089)
at android.content.res.Resources.loadDrawable(Resources.java:3939)
at android.content.res.TypedArray.getDrawable(TypedArray.java:886)
at android.graphics.drawable.AnimationDrawable.inflateChildElements(AnimationDrawable.java:324)
at android.graphics.drawable.AnimationDrawable.inflate(AnimationDrawable.java:294)
at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:2549)
at android.graphics.drawable.Drawable.createFromXml(Drawable.java:2320)
at android.content.res.Resources.loadDrawableForCookie(Resources.java:4210)
at android.content.res.Resources.loadDrawable(Resources.java:4089)
at android.content.res.Resources.getDrawable(Resources.java:2005)
at android.content.res.Resources.getDrawable(Resources.java:1987)
at android.content.Context.getDrawable(Context.java:464)
at android.view.View.setBackgroundResource(View.java:18537)

我的 Drawable 文件夹中有不同的动画文件。这是我正在运行的 xml 设置。

anim_sprite_run.xml

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item android:drawable="@drawable/run0001" android:duration="50" />
    <item android:drawable="@drawable/run0002" android:duration="50" />
    <item android:drawable="@drawable/run0003" android:duration="50" />
    <item android:drawable="@drawable/run0004" android:duration="50" />
    <item android:drawable="@drawable/run0005" android:duration="50" />
    <item android:drawable="@drawable/run0006" android:duration="50" />
    <item android:drawable="@drawable/run0007" android:duration="50" />
    <item android:drawable="@drawable/run0008" android:duration="50" />
    <item android:drawable="@drawable/run0009" android:duration="50" />
    <item android:drawable="@drawable/run0010" android:duration="50" />
    <item android:drawable="@drawable/run0011" android:duration="50" />
    <item android:drawable="@drawable/run0012" android:duration="50" />
    <item android:drawable="@drawable/run0013" android:duration="50" />
    <item android:drawable="@drawable/run0014" android:duration="50" />
    <item android:drawable="@drawable/run0015" android:duration="50" />
    <item android:drawable="@drawable/run0016" android:duration="50" />
    <item android:drawable="@drawable/run0017" android:duration="50" />
    <item android:drawable="@drawable/run0018" android:duration="50" />
    <item android:drawable="@drawable/run0019" android:duration="50" />
    <item android:drawable="@drawable/run0020" android:duration="50" />
    <item android:drawable="@drawable/run0021" android:duration="50" />
    <item android:drawable="@drawable/run0022" android:duration="50" />
    <item android:drawable="@drawable/run0023" android:duration="50" />
    <item android:drawable="@drawable/run0024" android:duration="50" />
    <item android:drawable="@drawable/run0025" android:duration="50" />
</animation-list>

在代码中,我像这样开始运行动画

ivSprite.setBackgroundResource(R.drawable.anim_sprite_run);
            ivSprite.post(new Runnable() {
                @Override
                public void run() {
                    mAnimationDrawable = (AnimationDrawable) ivSprite.getBackground();
                    mAnimationDrawable.start();
                }
            });

10 秒后,我调用另一个引用睡眠动画的代码 sn-p。这是由于OOM而崩溃的地方

ivSprite.setBackgroundResource(R.drawable.anim_sprite_sleep);
            ivSprite.post(new Runnable() {
                @Override
                public void run() {
                    mAnimationDrawable = (AnimationDrawable) ivSprite.getBackground();
                    mAnimationDrawable.start();
                }
            });

在调用睡眠动画之前,我尝试了以下方法:

ivSprite.setBackgroundResource(0);
ivSprite.clearAnimation();
mAnimationDrawable.stop();

我尝试将背景设置为空,以清除以前的动画。然后我调用 clearAnimation() 以获得额外的保证。最后我停止了之前的动画。这些都不能防止OOM错误,我没有想法。

提前感谢您的帮助。

【问题讨论】:

    标签: android animation out-of-memory animationdrawable


    【解决方案1】:

    我想出了一个解决方案!这是我一直在尝试的一切的高潮。

    但是,将动画移动到 drawable-nodpi 似乎是防止 OOM 错误的关键。 Android 可能会将资源默认设置为 /drawable-mdpi。

    此外,我添加了几行代码来帮助管理内存。我使我的 mAnimationDrawable 对象为空,并且我还调用了垃圾收集器。希望这些解决方案可以帮助其他使用精灵动画的人。干杯!

    ivSprite.setBackgroundResource(0);
    ivSprite.clearAnimation();
    mAnimationDrawable.stop();
    mAnimationDrawable = null;
    // invoke garbage collector
    System.gc();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-02
      • 1970-01-01
      • 1970-01-01
      • 2017-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-01
      相关资源
      最近更新 更多