问题描述
重复进入Activity再退出的操作,出现OutOfMemoryError。
问题分析
回退到上一个版本,重复问题的复现步骤,并没有出现内存溢出现象,于是将范围缩小到新版本中添加的新功能上面。将页面新添加的图片自动轮播控件去掉重试,发现没有出现内存溢出。所以问题应该是出在这个自定义控件上。(虽然也可能存在其他原因,但是这个控件一定是有问题的!)
自定义控件中使用了ViewPager
,自动翻页通过postDelayed()
方法定时执行翻页线程实现。查看View
的postDelayed()
方法的源码可发现,里面是通过将action
即Runnable
线程插入到了ViewPager
的Handler
中。上网查找ViewPager内存溢出相关资料看到如下一段:
Activity
想要销毁的话,会销毁Handler
,Handler
要想销毁的话,Handler
中不能有任务和Message
,因为发送的是延时的任务,因此Handler
中很有可能有任务执行,有任务执行的时候Handler
销毁不了,Handler
又持有Activity
的引用,因此造成一个死循环,导致Activity
销毁失败。
虽然这个是针对Activity
中的Handler
,但是其中Handler
的销毁原理应该是相同的。 再结合崩溃时的Log,得出结论就是,自定义控件中的内存溢出是由于Handler
中存在未执行完成的Message
导致。
解决方案
-
在自定义View需要销毁时,执行
handler.removeCallbacksAndMessages(null);
方法,主动清空Handler
中的任务。 -
根据Activity生命周期控制是否执行
ViewPager
的postDelayed()
方法,只有在当前Activity
或控件可见时才在Handler
中插入翻页线程。不可见时,执行ViewPager
的removeCallbacks()
方法取消对应的线程或removeCallbacksAndMessages()
方法清空其任务列表。
网友评论