Android - 释放分配的内存AnimationDrawable正在用完
Posted
技术标签:
【中文标题】Android - 释放分配的内存AnimationDrawable正在用完【英文标题】:Android - releasing allocated memory AnimationDrawable is using up 【发布时间】:2014-11-14 07:20:56 【问题描述】:我有一个复杂的战斗系统,它有 1 个父 Activity,然后是几个子类,它们通过扩展 Battle 并将上下文传递给这些类来访问 BattleActivity 的静态变量。
这一切似乎工作正常,但是我在从内存中释放所有 AnimationDrawables 时遇到问题。一场战斗总共可以使用 24 个 DrawableAnimations。现在还可以,但是每次用户遇到一个新怪物时,就会有 4 个 AnimationDrawables 添加到内存中,这会慢慢地导致我的应用程序因 anb Out of Memory 异常而崩溃。
因此,我真的需要找到一种方法来释放我的战斗系统所占用的所有内存。目前,我在 Sony Z2 上进行测试,当用户进入战斗时,内存从 91mb 增加到 230mb。战斗结束后,我需要将此内存使用量恢复到 91mb。我添加了一些非常基本的代码 sn-p 让您了解应用程序当前的流程以及我正在尝试做什么来释放内存。
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();
【问题讨论】:
你真的有你传递应用程序上下文的静态变量吗?我认为他们会比你的可绘制对象更早地杀死你的应用程序 是的,这仅适用于我的战斗方面,因为我不希望我的所有代码都在同一个 Activity 中,而是简单地扩展这个类,以便我仍然可以访问 UI。因为我需要能够在加载 Activity 之前加载所有 AnimationDrawables,以便在用户进入战斗时动画可以流畅 【参考方案1】:首先我认为你不能对AnimationDrawable
进行任何回收,除非你离开它们被声明的范围。不要中继System.gc();
,让GC自动为你释放这些内存。
访问BattleActivity的静态变量
这是你的第一个错误。如果你使用静态变量,即使你离开你的活动,它们都在那里,你肯定会得到 OOM。
因此,我真的需要找到一种方法来释放我所有的记忆 我一退出战斗系统就开始了。
如果您将所有变量声明为非静态变量,那么当您离开它们定义的范围时,您将不会得到 OOM。虽然如果在活动运行期间创建 AnimationDrawable
没有任何界限,您可能会得到 OOM。
【讨论】:
我已经修改了我的代码,因此我不再使用静态 AnimationDrawable,但是即使在 Activity 被销毁并且用户返回到游戏地图页面之后,仍然存在释放内存的问题。还有其他想法吗? 你现在有什么问题? 好吧,简单地说,AnimatonDrawables 的内存没有被释放 我不确定,但我认为当您离开该活动时,gc 不会立即运行,我认为它仅在您需要更多内存且没有足够内存时运行,所以请四处看看它是否会做任何清洁与否。【参考方案2】:使用静态 Drawable(s) 或 View(s) 会导致内存泄漏,因为 drawable 是有状态的。
您可以检查任何其他静态 Drawable(s) 或 View(s) 并删除它们或调用
drawable.setCallback(null);
你不能回收 Drawable 对象,调用 System.gc() 不是一个好习惯
您的应用似乎在某处出现内存泄漏,如果您尝试了上述方法并且内存仍以该速度扩展,请考虑使用memory analysis 来缩小问题范围。
【讨论】:
我不认为这是我遭受内存泄漏的事实,我认为这是可绘制使用的内存剪切量。我的意思是在一次加载时我有 30 个 AnimationDrawable 需要加载,每个包含大约 15 个图像,每个图像 256 像素 x 256 像素。因此,正如预期的那样,内存使用量猛增(根据设备加载也需要 2-4 秒)。这是我可以处理的,但是完成后我需要以某种方式释放该内存。每次遇到新怪物时,都会在内存中添加另外 5 个 AnimationDrawables 是的,但是如果您的 Activity 没有泄漏,则应根据需要释放内存,如果您在关闭 Activity 后手动调用 System.gc(),则这些 Drawable(s) 应从内存中清除,除非有泄漏。如果除了确保没有使用静态 Drawable 并且我提到的其他事情使它们在完成时指向 null 以避免可能的徘徊 我想我今晚必须研究一下,因为需要从所有 ImageViews 和 ImageButtons 中删除静态,然后才能正确测试它。检查内存泄漏和内存分析工具的背心方法是什么? 如果您的内存使用率一直在上升,这表明存在内存泄漏,请查看这些链接以了解如何查找泄漏,android-developers.blogspot.com/2011/03/… 和 developer.android.com/tools/debugging/debugging-memory.html 例如拥有一个静态 ImageView 会导致整个 Activity 被泄露(留在内存中),你应该摆脱所有这些静态 View(s) 和 Drawable(s)以上是关于Android - 释放分配的内存AnimationDrawable正在用完的主要内容,如果未能解决你的问题,请参考以下文章