9

I have a complex Battle system which has 1 parent Activity and then several child classes which access the static variables of the BattleActivity by extending Battle and passing the context to those classes.

This all seems to be working fine, however I am having an issue with releasing all my AnimationDrawables from memory. There can be a total of 24 DrawableAnimations used throughout a battle. This is ok for now, however every time the user encounters a new monster then 4 more AnimationDrawables are added to memory which will slowly but surley cause my App to Crash with anb Out of Memory exception.

Therefore, I really need to find a way to release all the memory my battle system takes up as soon as I exitit. Currently, I am testing on a Sony Z2 and when the user enters a battle the mmeory increases from 91mb to 230mb. I need to get this memory usage back down to 91mb when the battle has compelted. I have added some very basic code snippet to give you an idea of how the app currently flows and what I am trying to do to release the memory.

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();
    }
}
4

2 回答 2

0

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

访问 BattleActivity 的静态变量

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

因此,我真的需要找到一种方法,在我退出战斗系统后立即释放所有内存。

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

于 2014-11-08T03:59:58.180 回答
0

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

您可以检查任何其他静态 Drawable(s) 或 View(s) 并摆脱它们或调用

drawable.setCallback(null);

您不能回收 Drawable 对象,调用 System.gc() 不是一个好习惯

似乎您的应用程序在某个地方遇到了内存泄漏,如果您尝试了上述方法并且内存仍然以该速度扩展,那么请考虑进行内存分析以缩小问题范围。

于 2014-11-13T10:52:49.427 回答