-
Notifications
You must be signed in to change notification settings - Fork 779
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
2019-03-08: 自定义 Handler 时如何有效地避免内存泄漏问题? #1
Comments
1.自定义的静态handler |
弱引用会不会出现问题 |
不加弱引用的时候 如果GC不了 那岂不是GG了 |
现在手机都12G RAM,一个小小的handler就能让他崩溃吗 |
我竟无言以对 流弊流弊 |
Your this kind of train of thought is incorrect, upstairs consciousness is how to avoid the happening of the problem, your train of thought is to do not have a problem namely, it is not my business.The train of thought decides the way out, big brother, see the gap? |
God, can we drink together? |
Sure |
Sure ! |
使用弱引用是对的,静态内部类也是对的。
个人写的Handler,且没有耗时操作。没必要保护。 |
是的,正如楼上所说,其实正常情况下是不会内存泄漏的,除非handler队列等待太久(什么情况会这样呢?anr?延时太久?) |
对我而言,handler改为弱引用是一改而论(大家只考虑在activity问题,handler引用了activity),解决问题可以传activity弱引用给handler就行,或者在onresume恢复,onpause移除,谁能保证ondestroy能执行??万一没执行呢?如果在service后台用到handler,难道我也弱引用?合理使用handler,要明白为什么泄漏,不是所有场景都能用弱引用,没记错 高版本内存回收策略会先回收弱软引用,,,再说了,内存高就高,,,,,用户区能存活多久。。。 |
我觉得解决方法很简单 而泄露的根本原因就是你activity退出以后这个message还没有被处理完,如果这个message处理完你什么都不做也不会泄露,不过这个handler可能大部分执行的是一个类似联网的异步任务,所以activity退出出现内存泄漏就是因为这个message还没被处理完 |
多谢沐风大佬的邀请,本人会一一回复面试题,抛砖引玉,借花献佛,如果有错误,还请各位指出。 在Android系统中,Handler是一个消息发送和处理机制的核心组件之一,与之配套的其他主要组件还有Looper和Message,MessageQueue。 Handler有两个主要作用:
Handler是由系统所提供的一种异步消息处理的常用方式,一般情况下不会发生内存泄露。 Handler为什么可能造成内存泄漏。这里的内存泄漏,常常指的是泄漏了Activity等组件。
这有什么问题呢。问题在于该Handler的实例采用了内部类的写法,它是ShanActivity这个实例的内部类,在Java中,关于内部类有一个特点:在java中,非静态的内部类和匿名内部类都会隐式的持有一个外部类的引用。所以,该handler实例持有了ShanActivity的一个引用。 生命周期较短的组件引用了生命周期较长的组件。Handler就是一种典型的示例,以上面的代码举例。ShanActivity可能会被泄漏,也就是该组件没有用了,比如调用了finish()后,垃圾回收器却迟迟没有回收该Activity。原因出在该实例的handler内部类引用了它,而该handler实例可能被MessageQueue引用着。 从上面的说法中,可以思考得到相应的解决方法:
这里需要了解一下关于Java里面引用的知识:
第三种,需要一些额外的代码,比较通用。
第四种方式,抽取做单独封装。 /**
* 实现回调弱引用的Handler
* 防止由于内部持有导致的内存泄露
* 传入的Callback不能使用匿名实现的变量,必须与使用这个Handle的对象的生命周期一
* 致否则会被立即释放掉了
*/
public class WeakRefHandler extends Handler {
private WeakReference<Callback> mWeakReference;
public WeakRefHandler(Callback callback) {
mWeakReference = new WeakReference<Handler.Callback>(callback);
}
public WeakRefHandler(Callback callback, Looper looper) {
super(looper);
mWeakReference = new WeakReference<Handler.Callback>(callback);
}
@Override
public void handleMessage(Message msg) {
if (mWeakReference != null && mWeakReference.get() != null) {
Callback callback = mWeakReference.get();
callback.handleMessage(msg);
}
}
} 由于是弱引用,当该类需要被回收时,可以直接被回收掉。 WeakRefHandler的使用时如下: private Handler.Callback mCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch(msg.what){
}
return true;
}
};
private Handler mHandler = new WeakRefHandler(mCallback); 本人最近在学习C,个人感觉应该使用第一个解决方法,因为你要深刻理解你的代码是干什么的,在哪干活的,还有在什么时候应该回收——仅是个人看法,如有不同,请忽略。 |
默认的handler 在处理信息时可以延迟处理, 那么就会导致activity关闭时 有可能消息还未处理完毕 ,此时未被处理的消息会持有handler, handler又会持有activity, 从而导致内存泄漏。 |
上面都回答了很多解决方案了,我就说下实操中一些注意事项,可能会用到。 |
加油吧同学们, 学无止境啊 |
如果所有的app都跟你一样想的话,那肯定都崩溃了 |
你知道什么是ROM什么是RAM吗? |
当你说出这句话时,给人的感觉是你不知道啥是RAM 啥是ROM |
hahaha |
自定义handler对象,传入LifecycleOwner对象,监听activity的ondestroy回调,在用ondestroy的时候把消息remove掉。具体使用:https://github.com/AlanCheen/Pandora/blob/master/pandora-basic/src/main/java/me/yifeiyuan/pandora/LifecycleHandler.java |
哈哈哈哈 |
内存泄漏发生的主要原因:当前对象需要被销毁时,由其他对象(包含外部对象或者非静态内部类)持有当前对象的引用,导致当前对象释放不了;也可以抽象的说成是生命周期长的对象持有生命周期短的对象的引用 自定义 handler 导致内存泄漏发生的主要原因:当 activity 调用 finish 方法时,由于消息队列中有没被执行完的 message,message 持有 handler 的引用,handler 作为内部类又持有外部 activity 的引用,导致activity无法被释放; 解决办法:
|
直接清除队列里面的message不可以吗? |
看了大家写了这么多,还是很有收获的,目前基本都在使用 kotlin 开发,看见如上的回答中,有一个 kotlin 版本,写法比较奇怪,说一下自己的看法:
奇怪的地方:居然把一个所谓的静态内部类定义到了 companion object 模块 ???(该模块只用来定义静态字段和静态方法) kotlin 中应该怎么写呢:
kotlin 的内部类需要用 inner class 关键字申明,不适用 inner 关键字修饰的类,称之为 嵌套类,不持有外部类的引用,请放心使用哈 |
千里之堤,毁于蚁穴 |
Handler 引起的内存泄露相关知识点:
|
1.自定义静态的Handler |
Handler内存泄露的根源: 网友提的 弱引用算长知识了 |
1.将Handler自定义成静态类 弱引用Activity实例 |
1、静态内部类 |
通常大家都喜欢在ondestory的时候调用mHandler.removeCallbacksAndMessages(null)
通过标志位 来判断是否是destroy的状态来加快释放的速度,算是优化的一点 |
dalvik.vm.heapsize 指定了堆空间大小。不是12G的ram应用就能用12G的 |
现在手机内存比我电脑的都高 |
handler.removeCallbacksAndMessages(null)清空消息队列 |
群里给出的答案以及讨论都很不错,我这里结合Profiler 直观的将Activity泄漏不同情况展示出来。 具体的可以参考我这篇文章自定义Handler内存泄漏 (图文版) |
No description provided.
The text was updated successfully, but these errors were encountered: