handler的内存泄漏问题

Handler的内存泄漏的问题?

所谓的内存泄漏就是这个对象没有任何使用价值了但是由于任然存在引用导致内存被占用了垃圾回收器回收不了。。。。。

至于为什么会出现内存泄漏呢?

这里面的原理是很深很深的,因为new 的handler是一个内部类对象对外部类对象有个隐试强引用。

内部类对外部类有个隐试强引用其实并没有导致内存泄漏,尽管activity的引用被内部类对象持有着,大不了内部类对象先被回收,外部类还是可以被回收的,关键是由于上一篇文章中我特地强调了在Handler内部有个msg.target=this,这个内部类handler被消息队列中的消息所持有,所以只要消息队列里有消息,这个handler就没法被清理,这样就导致外部类的activity即便退出了也没法被gc回收,这样就内存泄漏了。基于我这点说明那么我目前可以从三点来解决这个内存泄漏问题。

引申一下知识点:

Java中的引用有四种,垃圾回收器对垃圾进行回收的时候氛围搜索算法和一个回收算法。

搜素算法使用的是引用计数算法,就是一个对象一个对象遍历,当一个对象没被别人引用的时候计数器会被加1,如果这个引用消失掉,计数器就会减一,当引用计数器为0,ok。垃圾回收期就会将其列为可回收对象,gc运行的时候不定期的将其清理掉,将内存给释放掉。当我们内部类创建的时候对外部类就会有一个隐试的强引用。所谓隐试,就是我们看不见,但是虚拟机设计的就是有个引用

因为是个强引用,所以这个内部类对象永远不能被清理掉,但是当我们退出界面,外部类的MainActivity按理说也应该被清理掉,但是由于存在内部类的引用导致这个activity对象也永远清理不掉,而这个内部类由于MessageQueen里的meg对其有个引用,所以导致handler清理不了,于是activity也就清理不了,所以导致内存泄漏,解决的办法就是把handler设置成静态的,这样静态内部类对外部类就不存在隐试强引用的关系了。

四种引用类型,

1:强引用。当一个对象被强引用引用的时候,GC永远没法将其清理掉,除非oom,虚拟机都挂了,肯定也挂了

2: 软引用,当系统内存不足的时候被GC掉

3:弱引用,当GC发现它的时候就将其干掉。引申一下,假如给这个弱引用加一个queen的话(记得有个重载方法可以加这个参数),被清理以后的引用会被放到这个queen里,然后我们可以通过检测这个queen是否为null观察对象有没有被清理,null说明没被清理,不为null说明被清理了,内存检测公共Leakcanary利用这个原理做的,在多一嘴,内存检测公共还有Mat,DDMS的heap可以检测

4:虚引用,不是一个真正的引用类型,是用来检测内存泄漏的

1:第一种解决方案给handler加静态这样就不存在内部类对外部类隐试强引用问题了

这种提交方式:

2:还有种解决办法就是用软引用。当内存不足的时候还是会清理,就是我们继承handler的类,然后我们创建这个自定义handler对象放进自己new的软引用中,这样内存不足的时候就会把软引用的对象给清理掉

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myhandler2 = new Myhandler2();
        softReference = new SoftReference<Handler>(myhandler2);
    }
class  Myhandler2 extends Handler{
     WeakReference<Context> weak;
}
    @Override
    public void handleMessage(Message msg) {
        String s=(String)msg.obj;
        Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show();
        super.handleMessage(msg);
    }
}
//点击按钮实现的子线程向主线程传消息
public void click(View v){
    new Thread(new Runnable() {

        @Override
        public void run() {
            Message msg=new Message();
            msg.what=13;
            msg.obj="dasdasd";
            softReference.get().sendMessage(msg);

        }
    }).start();
}

3:第三种清理消息队列的消息

就是在activity的destory或者finish的时候调用myhandler2.removeCallbacksAndMessages(null);这样把消息给清空,就不存在meg.target=handler。就业不存在这个MessageQueen的消息持有这个handler的引用了,这样handler就可以被清理了。

时间: 2024-10-17 21:00:24

handler的内存泄漏问题的相关文章

从使用Handler致内存泄漏角度源码追踪Handler工作机制

使用Handler时内存泄漏分析 在Android中,处理完异步任务后常常会在主线程进行一些操作,所以我们可能会使用到Handler,下面是Handler的常见使用方法: public class MainActivity extends AppCompatActivity { private Handler mHanlder = new Handler() { @Override public void handleMessage(Message msg) { //TODO } }; } 但是

Android Handler 避免内存泄漏的用法总结

Android开发经常会用到handler,但是我们发现每次使用Handler都会出现:This Handler class should be static or leaks might occur(null)这样的提示.Android lint就是为了提示我们,这样使用Handler会容易造成内存泄漏.但是你会发现其实改成static并没有什么用.因为这并没有解决这个问题的根本. 首先,我们得确认,为什么会有内存泄漏?因为Handler是基于消息的.每次new 出Handler,都会创建一个

Android Handler 防内存泄漏

package com.tv.ui.metro.utils; import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.View; import com.thunder.ktv.thunderjni.thunderapi.TDHotspot;import co

Android性能优化之内存泄漏

综述 内存泄漏(memory leak)是指由于疏忽或错误造成程序未能释放已经不再使用的内存.那么在Android中,当一个对象持有Activity的引用,如果该对象不能被系统回收,那么当这个Activity不再使用时,这个Activity也不会被系统回收,那这么以来便出现了内存泄漏的情况.在应用中内出现一次两次的内存泄漏获取不会出现什么影响,但是在应用长时间使用以后,若是存在大量的Activity无法被GC回收的话,最终会导致OOM的出现.那么我们在这就来分析一下导致内存泄漏的常见因素并且如何

Android 内存泄漏

在分享会上听小伙伴对这部分内容做了讲解,发觉在平时的编程中确实有很多问题没有注意到,故记录下来分享给各位,也欢迎各位不吝赐教纠正文中不足之处. 内存泄漏与内存溢出: 内存溢出简单讲就是程序运行要求的内存大于虚拟机能提供的最大内存,会导致程序崩溃,也就是我们常见的Out Of Memory错误. 内存泄露指程序未能释放已经不再使用的内存.内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于程序设计的失误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费.少量的内存

android 内存泄漏检测工具 LeakCanary 泄漏金丝雀

韩梦飞沙 yue31313 韩亚飞 han_meng_fei_sha [email protected] 内存泄漏检测工具 android 内存泄漏检测工具 ======== 内存泄漏 就是  无用的对象没有被回收,占用着内存,使得可用内存变小了. 如何检测内存泄漏, 可以使用 LeakCanary来检测内存泄漏. leak  是 泄漏的意思.. Canary 是 金丝雀 的意思. 在运行 应用的时候, 泄漏金丝雀 如果检测到内存泄漏 会显示一个通知. ======== LeakCanary捕获

Android内存泄漏查找和解决

Android内存泄漏查找和解决 目录: 内存泄漏的概念 一个内存泄漏的例子 Java中"失效"的private修饰符 回头看内存泄漏例子泄漏的重点 强引用与弱引用 解决内部类的内存泄漏 Context造成的泄漏 使用LeakCanary工具查找内存泄漏 总结 一.内存泄漏概念 1.什么是内存泄漏? 用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元.直到程序结束.即所谓的内存泄漏. 其实说白了就是该内存空间使用完毕之后未回收 2.内存泄漏会导致的问题 内

安卓常见引起内存泄漏的五种情况

1,单例引起的内存泄漏----解决办法 将context生命周期和application保持一致 public class SingletonAppliationContext {    private static SingletonAppliationContext instance;    private Context context;    private SingletonAppliationContext(Context context) {        this.context

Handler系列之内存泄漏

本篇简单的讲一下平常使用Handler时造成内存泄漏的问题. 什么是内存泄漏?大白话讲就是分配出去的内存,回收不回来.严重会导致内存不足OOM.下面来看一下造成内存泄漏的代码: public class MemoryLeakActivity extends Activity { private MyHandler mHandler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(save