在android 项目开发过程中,不小心可能就会导致activity的内存泄露,即使用户在使用APP的时候并没有感受到内存泄露给APP带来毁灭性的奔溃,但我们开发者可以通过调试能够很明显的看到有些占用的内存死也GC不掉。
OK ,隔壁家老伍来讲解一个,老伍亲身经历的怪事,APP在启动时我们都有加启动页面,为了好看,有时还会添加一些动画效果,可怕的是启动页面是一张比较大点的图片,启动完以后Activity被finish()掉,我们的理想是希望启动页结束后,占用的内存也能过及时销毁,避免一些无谓的内存占用。怪就怪这块内存怎么GC都GC不掉,佛主啊,佛主,这是是为啥子罗。
笔者接下来找原因,java的内存回收机制还是很强大的,很明显这个快占用的内存一定还被某个对象引用着,代码分析下来启动页面时加了一个过度动画,项目中有一个Util类,类里面提供了两个静态成语变量
private static Animation alphaShowAnimation = null;
private static Animation alphaHideAnimation = null;
加载动画的方法 public static void startViewLeftAnimation(final View view, boolean isShow, Contextcontext)
注意参数View被final 修饰了,函数体里面的方法实现
if (alphaHideAnimation == null) {
alphaHideAnimation = AnimationUtils.loadAnimation(context, R.anim.animation_hide);
}
alphaHideAnimation.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation arg0) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationRepeat(Animation arg0) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationEnd(Animation arg0) {
// TODO Auto-generated method stub
view.setVisibility(View.GONE);
}
});
注意看在动画结束后调用了view.setVisibility(View.GONE), 也就是说使用了Activity 传递过来的view ,那么问题来了alphaHideAnimation又是静态变量,它生命周期老长老长的,没出意外的话可以活500年,仔细分析在一个静态成员的变量中保留了Activity里面的一个视图,可恶的是视图中保留了Context的引用,这个时候就产生了一个对象长期被引用,导致Activity无法被GC掉,Activity占用的内存也无法被GC掉。这个时候内存溢出发生了。
建议动画少用静态成员,尽量保持生命周期在函授体内,使用静态成员时要检查有没有长期引用且需要销毁的对象。
这是一个简单的Actiivty内存溢出,可以通过代码逻辑就能够分析出来,复杂一点的我们使用Mat工具来分析。