App调试内存泄露之Context篇(下)
2014-12-10 13:26
190 查看
接着《Android学习系列(36)--App调试内存泄露之Context篇(上)》继续分析。
5. AsyncTask对象
我N年前去盛大面过一次试,当时面试官极力推荐我使用AsyncTask等系统自带类去做事情,当然无可厚非。
但是AsyncTask确实需要额外注意一下。它的泄露原理和前面Handler,Thread泄露的原理差不多,它的生命周期和Activity不一定一致。
解决方案是:在activity退出的时候,终止AsyncTask中的后台任务。
但是,问题是如何终止?
AsyncTask提供了对应的API:public final boolean cancel (boolean mayInterruptIfRunning)。
它的说明有这么一句话:
cancel是不一定成功的,如果正在运行,它可能会中断后台任务。怎么感觉这话说的这么不靠谱呢?
是的,就是不靠谱。
那么,怎么才能靠谱点呢?我们看看官方的示例:
官方的例子是很好的,在后台循环中时刻监听cancel状态,防止没有及时退出。
为了提醒大家,google特意在AsyncTask的说明中撂下了一大段英文:
可怜我神州大陆幅员辽阔,地大物博,什么都不缺,就是缺对英语阅读的敏感。
AsyncTask适用于短耗时操作,最多几秒钟。如果你想长时间耗时操作,请使用其他java.util.concurrent包下的API,比如Executor, ThreadPoolExecutor 和 FutureTask.
学好英语,避免踩坑!
6. BroadcastReceiver对象
... has leaked IntentReceiver ... Are you missing a call to unregisterReceiver()?
这个直接说了,种种原因没有调用到unregister()方法。
解决方法很简单,就是确保调用到unregister()方法。
顺带说一下,我在工作中碰到一种相反的情况,receiver对象没有registerReceiver()成功(没有调用到),于是unregister的时候提示出错:
有两种解决方案:
方案一:在registerReceiver()后设置一个FLAG,根据FLAG判断是否unregister()。网上搜到的文章几乎都这么写,我以前碰到这种bug,也是一直都这么解。但是不可否认,这种代码看上去确实有点丑陋。
方案二:我后来无意中听到某大牛提醒,在Android源码中看到一种更通用的写法:
7. TimerTask对象
TimerTask对象在和Timer的schedule()方法配合使用的时候极容易造成内存泄露。
泄露的点是,忘记cancel掉Timer和TimerTask实例。cancel的时机同cursor篇说的,在合适的时候cancel。
8. Observer对象。
Observer对象的泄露,也是一种常见、易发现、易解决的泄露类型。
先看一段正常的代码:
看完示例,我们来看看病例:
靠,谁这么偷懒,把SettingObserver搞个匿名对象传进去,这可如何是好?
所以,有些懒是不能偷的,有些语法糖是不能吃的。
解决方案就是, 在不需要或退出的时候delete这个Observer。
注意一点,不同的注册方法,不同的反注册方法。
9. Dialog对象
android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@438afa60 is not valid; is your activity running?
一般发生于Handler的MESSAGE在排队,Activity已退出,然后Handler才开始处理Dialog相关事情。
关键点就是,怎么判断Activity是退出了,有人说,在onDestroy中设置一个FLAG。我很遗憾的告诉你,这个错误很有可能还会出来。
解决方案是:使用isFinishing()判断Activity是否退出。
早完早释放!
10. 其它对象
以Listener对象为主,"把自己搭进去了,切记一定要及时把自己放出来"。
11. 小结
结合本文Context篇和前面Cursor篇,我们枚举了大量的泄露实例,大部分根本原因都是相似的。
通过分析这些例子后,我们应该能理解APP层90%的内存泄露情况了。
至于怎么发现和定位内存泄露,这是另外一个有意思的话题,现在只能说,有方法有工具。
/article/4732869.html
5. AsyncTask对象
我N年前去盛大面过一次试,当时面试官极力推荐我使用AsyncTask等系统自带类去做事情,当然无可厚非。
但是AsyncTask确实需要额外注意一下。它的泄露原理和前面Handler,Thread泄露的原理差不多,它的生命周期和Activity不一定一致。
解决方案是:在activity退出的时候,终止AsyncTask中的后台任务。
但是,问题是如何终止?
AsyncTask提供了对应的API:public final boolean cancel (boolean mayInterruptIfRunning)。
它的说明有这么一句话:
是的,就是不靠谱。
那么,怎么才能靠谱点呢?我们看看官方的示例:
为了提醒大家,google特意在AsyncTask的说明中撂下了一大段英文:
AsyncTask适用于短耗时操作,最多几秒钟。如果你想长时间耗时操作,请使用其他java.util.concurrent包下的API,比如Executor, ThreadPoolExecutor 和 FutureTask.
学好英语,避免踩坑!
6. BroadcastReceiver对象
... has leaked IntentReceiver ... Are you missing a call to unregisterReceiver()?
这个直接说了,种种原因没有调用到unregister()方法。
解决方法很简单,就是确保调用到unregister()方法。
顺带说一下,我在工作中碰到一种相反的情况,receiver对象没有registerReceiver()成功(没有调用到),于是unregister的时候提示出错:
方案一:在registerReceiver()后设置一个FLAG,根据FLAG判断是否unregister()。网上搜到的文章几乎都这么写,我以前碰到这种bug,也是一直都这么解。但是不可否认,这种代码看上去确实有点丑陋。
方案二:我后来无意中听到某大牛提醒,在Android源码中看到一种更通用的写法:
7. TimerTask对象
TimerTask对象在和Timer的schedule()方法配合使用的时候极容易造成内存泄露。
Observer对象的泄露,也是一种常见、易发现、易解决的泄露类型。
先看一段正常的代码:
所以,有些懒是不能偷的,有些语法糖是不能吃的。
解决方案就是, 在不需要或退出的时候delete这个Observer。
android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@438afa60 is not valid; is your activity running?
一般发生于Handler的MESSAGE在排队,Activity已退出,然后Handler才开始处理Dialog相关事情。
关键点就是,怎么判断Activity是退出了,有人说,在onDestroy中设置一个FLAG。我很遗憾的告诉你,这个错误很有可能还会出来。
解决方案是:使用isFinishing()判断Activity是否退出。
10. 其它对象
以Listener对象为主,"把自己搭进去了,切记一定要及时把自己放出来"。
11. 小结
结合本文Context篇和前面Cursor篇,我们枚举了大量的泄露实例,大部分根本原因都是相似的。
通过分析这些例子后,我们应该能理解APP层90%的内存泄露情况了。
至于怎么发现和定位内存泄露,这是另外一个有意思的话题,现在只能说,有方法有工具。
/article/4732869.html
相关文章推荐
- Android学习之App调试内存泄露之Context篇(下)
- Android学习系列(36)--App调试内存泄露之Context篇(上)
- Android学习系列(36)--App调试内存泄露之Context篇(上)(下)
- Android学习系列(36)--App调试内存泄露之Context篇(上)
- Android学习系列--App调试内存泄露之Context篇(上)
- [Android Memory] App调试内存泄露之Context篇(下)
- Android学习系列(37)--App调试内存泄露之Context篇(下)
- App调试内存泄露之Context篇(下)
- App调试内存泄露之Context篇(上)
- App调试内存泄露之Context篇(上)
- App调试内存泄露之Context篇(下)
- App调试内存泄露之Context篇(上)
- App调试内存泄露之Context篇(下)-App调试内存泄露之Context篇(下)
- [Android Memory] App调试内存泄露之Context篇(上)
- Android学习系列(37)--App调试内存泄露之Context篇(下)
- App调试内存泄露之Context篇(下)
- App调试内存泄露之Context篇(下)
- App调试内存泄露之Context篇(上)
- App调试内存泄露之Context篇(上)
- Android学习系列--App调试内存泄露之Context篇(下)