Android - 释放分配的内存AnimationDrawable正在用完

时间:2014-09-19 16:17:51

标签: java android memory-management memory-leaks animationdrawable

我有一个复杂的Battle系统,它有1个父Activity,然后是几个子类,通过扩展Battle并将上下文传递给这些类来访问BattleActivity的静态变量。

这一切似乎都运行良好,但是我遇到了从内存中释放所有AnimationDrawables的问题。在整个战斗中总共可以使用24个DrawableAnimations。现在这是可以的,但是每次用户遇到一个新的怪物时,会有4个以上的AnimationDrawables被添加到内存中,这将慢慢地但是并且会导致我的应用程序崩溃,并且内存不足异常。

因此,我真的需要找到一种方法来释放我的战斗系统在我退出时占用的所有内存。目前,我正在测试Sony Z2,当用户参加战斗时,记忆从91mb增加到230mb。当战斗迫使我需要将这个内存使用量降低到91mb。我添加了一些非常基本的代码片段,让您了解应用程序当前的流程以及我要尝试释放内存的方法。

public class Battle extends Activity
{
     // I have several AnimationDrawables loaded into memory
     // These are then assigned the relevent animation to a button swicthing between these animations throughout my battle
    ImageButton btnChr1;
    AnimationDrawable cAnimHit1;
}

//This is the use of one of those AnimationDrawables
public class Battle_Chr_Anim extends Battle
{
    protected Context ctx;
    private ImageButton btnChr1;
    AnimationDrawable cAnimHit1;

    public Battle_Chr_Anim(Context c, ImageButton _btnChr1, AnimationDrawable _cAnimHit1) { 
        this.ctx = c;
        this.btnChr1 = _btnChr1;
        this.cAnimHit1 = _cAnimHit1;
    }

    // Bound the ImageButton
    int id = ctx.getResources().getIdentifier("idle", "drawable", ctx.getPackageName());
    img_chr1.setBackgroundResource(id);
    frameAnimation = (AnimationDrawable)img_chr1.getBackground();
    frameAnimation.start()

    // Loaded into memory ready so I can swicth them over quickly when user attacks
    int ca1 = ctx.getResources().getIdentifier("attack", "drawable", ctx.getPackageName());
    cAnimHit1 = (AnimationDrawable)chrHit1.getBackground();
    cAnimHit1.start();
}

public class Battle_Ended extends Battle
{
    protected Context ctx;

    public Battle_Ended(Context c) { 
        this.ctx = c;
    }

    //This is a dialog popup when the user completes the battle closing the battle activty
    void EndBattle()
    {
        ImageButton btnSubmit = (ImageButton)dialog.findViewById(R.id.imgBtnSubmit);
        btnSubmit.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent returnIntent = new Intent();
                setResult(RESULT_CANCELED, returnIntent);
                RecyleAllAnimations();
                dialog.dismiss();
                ((Activity) ctx).finish();
            }
        });
    }

    void RecyleAllAnimations()
    {
        // I want all AnimationDrawables from memory here, I believe the below line removes the one currently in use, however I have no way of releasing the other animations sitting in memory.
        img_chr1.setBackgroundResource(android.R.color.transparent);
        System.gc();
    }
}

2 个答案:

答案 0 :(得分:0)

首先,我认为你不能对AnimationDrawable进行任何回收,除非你离开宣布它们的范围。不要在System.gc();中继,让GC自动为你释放这些内存。

  

访问BattleActivity的静态变量

这是你的第一个错误。如果你使用静态变量,即使你离开你的活动他们都在那里你肯定会得到OOM。

  

因此,我真的需要找到一种方法来释放我的所有记忆   我退出后,战斗系统就会占用。

如果您将所有变量声明为非静态变量,那么当您离开定义的范围时,您将不会获得OOM。如果在活动运行期间创建AnimationDrawable而没有任何界限,则可能会获得OOM。

答案 1 :(得分:0)

使用静态Drawable(s)或View(s)将导致内存泄漏,因为drawables是有状态的。

您可以检查任何其他静态Drawable(s)或View(s)并删除它们或致电

drawable.setCallback(null);

您无法回收Drawable对象,并且调用System.gc()

不是一个好习惯

您的应用程序似乎在某处遇到了内存泄漏,如果您尝试了上述内容并且内存仍以该速率扩展,那么请考虑执行memory analysis来缩小问题范围。