精华内容
下载资源
问答
  • Handler内存泄漏

    2019-05-24 22:05:46
    Handler内存泄漏 关于Handler内存泄漏及解决办法: 原因: handler会持有activity的匿名引用 (因为内部类的原因,具体参考内部类实现),当activity要被回收时,因为handler在做耗时操作而没有被释放,从而内存...

    Handler内存泄漏

    1. 关于Handler内存泄漏及解决办法:
      • 原因:

        1. handler会持有activity的匿名引用 (因为内部类的原因,具体参考内部类实现),当activity要被回收时,因为handler在做耗时操作而没有被释放,从而内存泄漏
        2. 实例化Handler对象后,它就会主动与主线程的Looper的消息队列关联起来,所有发送到消息队列的Message都会拥有一个对Handler的引用,所以才由Looper处理消息时的回调Handler.handlerMessage(Message)来处理消息
      • public class SampleActivity extends Activity {
            private Handler mHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    //...
                }
            }
        }
        
      • 解决办法:

        • 将Handler设置为静态内部类(具体参考静态内部类和内部类区别),并使使Handler持有对Activity的弱引用

           public class SampleActivity extends Activity {
                   .......
                private static class MyHandler extends Handler {
                       private final WeakReference<SampleActivity> mActivity;
                       public MyHandler(SampleActivity activity) {
                           myActivity = new WeakReference<SampleActivity>(activity);
                       }
          	 		@Override
           	 		public void handleMessage(Message msg) {
           	 			SampleActivity activity = mActivity.get();
               			if (activity != null) {
           			...
          	 		}
                }
             }
          }
          
        • 在activity生命周期onDestroy()中调用Handler.removeCallback()方法

          
          // 清空消息队列,移除对外部类的引用
          @Override
          protected void onDestroy() {
              super.onDestroy();
              mHandler.removeCallbacksAndMessages(null);
          
          }
          //Handler源码中removeCallbacksAndMessages()注释含义
          /**
           * Remove any pending posts of callbacks and sent messages whose
           * <var>obj</var> is <var>token</var>.  If <var>token</var> is null,
           * all callbacks and messages will be removed.
           */
          public final void removeCallbacksAndMessages(Object token) {
              mQueue.removeCallbacksAndMessages(this, token);
          }
          

    内部类实现

    1. 内部类和静态内部类以及匿名内部类的应用
      • 内部类的优势:

        • 内部类方法可以访问盖内定义所在作用域的数据,包括私有数据

        • 内部类可以对同一个包中其他类隐藏

        • 想定义一个回调函数而且不像编写大量代码时,使用匿名内部类比较简洁

      • 原理:

        • 内部类的对象总有一个隐式引用,它指向了创建它的外部类对象

        • 编译器修改了所有内部类的构造器,添加了一个外围类的引用参数:

          public class Outer {
              ...
          class Inner {
              ...
              //Outer为外部类,Inner为内部类
              Outer out;
              public Inner(Outer outer) {
              out = outer;
          	}
          }
          }
          
      • 静态内部类:
        使用内部类只是为了把一个类隐藏在另一个类的内部,并不需要内部类引用外围类的对象。
        因此可以将内部类声明为static,以便取消产生的引用

    参考:
    https://juejin.im/post/5ccaa95ae51d453b222b7953

    https://github.com/francistao/LearningNotes/blob/master/Part1/Android/Handler内存泄漏分析及解决.md

    展开全文
  • handler内存泄漏

    2017-09-22 14:04:00
    handler内存泄漏原因有两个: 第一: public final Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); }};@Overrideprotected void onCreate(B...

    handler内存泄漏原因有两个:

    第一:

    public final Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
    super.handleMessage(msg);
    }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    new Thread(new Runnable() {
    @Override
    public void run() {
    load(url);
    handler.sendEmptyMessage(1);
    }
    }).start();

    }
    子线程耗时操作,当用户回到home,子线程还在运行,handler非静态内部类,持有外部类的引用,导致MainActivity无法回收,造成内存泄漏;


    第二:
    public final Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
    super.handleMessage(msg);
    }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    handler.postDelayed(new Runnable() {
    @Override
    public void run() {
    load(url);
    }
    },1000*60*5);

    }
    handler延时执行,5分钟之内,MainActivity回收不了,造成内存泄漏。

    解决方法 第一种:
       public MyHandler(MainActivity activity) {
    this.mActivity = new WeakReference<MainActivity>(activity);
    }
    @Override
    public void handleMessage(Message msg) {
    // super.handleMessage(msg);
    MainActivity mainActivity = mActivity.get();
    if (mainActivity == null) {
    return;
    }
    //code

    }
    }
    private final MyHandler mHandler = new MyHandler(this);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    new Thread(new Runnable() {
    @Override
    public void run() {
    load(url);
    mHandler.sendEmptyMessage(1);
    }
    }).start();

    }
    @Override
    protected void onDestroy() {
    super.onDestroy();
    mHandler.removeCallbacks(1);
    }

    解决方法 第二种:
    private static class MyHandler extends Handler{
    private final WeakReference<MainActivity> mActivity;

    public MyHandler(MainActivity activity) {
    this.mActivity = new WeakReference<MainActivity>(activity);
    }
    @Override
    public void handleMessage(Message msg) {
    // super.handleMessage(msg);
    MainActivity mainActivity = mActivity.get();
    if (mainActivity == null) {
    return;
    }
    //code

    }
    }
    private static final Runnable MyRunnable = new Runnable() {
    @Override
    public void run() {

    }
    };

    private final MyHandler mHandler = new MyHandler(this);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mHandler.postDelayed(MyRunnable,1000*60*5);

    }
    @Override
    protected void onDestroy() {
    super.onDestroy();
    mHandler.removeCallbacks(MyRunnable);
    }







    转载于:https://www.cnblogs.com/renjiemei1225/p/7574560.html

    展开全文
  • handler内存泄露

    2017-06-24 21:32:07
    Handler内存泄露原理及解决方法   作者 appcompat_v7 关注 2017.03.06 01:08 字数 1278 阅读 52评论 0喜欢 1 前言 因为Android采取了单线程UI模型,开发者无法在子线程中更新UI,为此...
     
    

    Handler内存泄露原理及解决方法

    144 
    作者  appcompat_v7 
    2017.03.06 01:08  字数 1278  阅读 52 评论 0

    前言

    因为Android采取了单线程UI模型,开发者无法在子线程中更新UI,为此Android为我们提供了Handler这个工具,可以开发者切换到主线程更新UI。

    示例

    首先看一段示例代码

    public class LeakCanaryActivity extends AppCompatActivity
    
        private  Handler mHandler;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            mHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
    
                }
            };
    
            Message message = Message.obtain();
            message.what = 1;
            mHandler.sendMessageDelayed(message,10*60*1000);
        }
    
    }

    这段代码的逻辑很简单,mHandler延时了10分钟发送消息,类似的代码在我们的项目中也经常出现,但是这样的代码会出现一个问题。

    问题

    我们在项目中集成 Square 的开源库 LeakCanary,有关这个库的介绍及使用请看:Github.LeakCanary

    我们首先打开 LeakCanaryActivity ,然后按返回键将这个Activity finish 掉。等待几秒屏幕上会弹出提醒和通知,这说明此时发生了内存泄露的现象。

    原因

    究竟是什么时候发生了内存泄露的问题呢?

    我们知道在Java中,非静态内部类会隐性地持有外部类的引用,二静态内部类则不会。在上面的代码中,Message在消息队列中延时了10分钟,然后才处理该消息。而这个消息引用了Handler对象,Handler对象又隐性地持有了Activity的对象,当发生GC是以为 message – handler – acitivity 的引用链导致Activity无法被回收,所以发生了内存泄露的问题。

    危害

    众所周知,内存泄露在 Android 开发中是一个比较严重的问题,系统给每一个应用分配的内存是固定的,一旦发生了内存泄露,就会导致该应用可用内存越来越小,严重时会发生 OOM 导致 Force Close。

    解决

    这个问题该如何解决呢?

    1. 使用弱引用

      首先我们需要理解一下相关概念:

      • 强引用:强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。
      • 软应用:如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。
      • 弱引用:弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

      用更直白的语言描述就是,java对于 强引用 的对象,就绝不收回,对于 软引用 的对象,是能不收回就不收回,这里的能不收回就是指内存足够的情况,对于 弱引用 的对象,是发现就收回,但是一般情况下不会发现。

      很显然,出现内存泄露问提的原因,就是 Handler 对 Activity 是强引用,导致 GC 在回收 Activity 时无法回收。为了解决这个问题,我们可以把 Handler 对 Activity 弱引用,这样 GC 就能把 Activity 及时的回收,从而杜绝了内存泄露的问题。

      public class NoLeakActivity extends AppCompatActivity {
      
          private NoLeakHandler mHandler;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
      
              mHandler = new NoLeakHandler(this);
      
              Message message = Message.obtain();
      
              mHandler.sendMessageDelayed(message,10*60*1000);
          }
      
          private static class NoLeakHandler extends Handler{
              private WeakReference<NoLeakActivity> mActivity;
      
              public NoLeakHandler(NoLeakActivity activity){
                  mActivity = new WeakReference<>(activity);
              }
      
              @Override
              public void handleMessage(Message msg) {
                  super.handleMessage(msg);
              }
          }
      }

      运行项目,并没有发生内存泄露的问题。

    2. 及时清除消息

      在原因中我们说到,正是因为被延时处理的 message 持有 Handler 的引用,Handler 持有对 Activity 的引用,形成了message – handler – activity 这样一条引用链,导致 Activity 的泄露。因此我们可以尝试在当前界面结束时将消息队列中未被处理的消息清除,从源头上解除了这条引用链,从而使 Activity 能被及时的回收。

      public class LeakCanaryActivity extends AppCompatActivity {
      
          private  Handler mHandler;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
      
              mHandler = new Handler() {
                  @Override
                  public void handleMessage(Message msg) {
                      super.handleMessage(msg);
      
                  }
              };
      
              Message message = Message.obtain();
              message.what = 1;
              mHandler.sendMessageDelayed(message,10*60*1000);
          }
      
          @Override
          protected void onDestroy() {
              super.onDestroy();
              mHandler.removeCallbacksAndMessages(null);
          }
      }

      运行项目,也没有发生内存泄露的问题。

     日记本

    如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!

    赞赏支持
    登录  后发表评论
    评论
    智慧如你,不想 发表一点想法咩~
    更多精彩内容

    披着狼皮的羊,愚昧的中国人

    狸小猫

    个人成长52本好书推荐|弗兰克

    弗兰克

    可我不喜欢你了

    曲尚菇凉
    展开全文
  • Handler 内存泄漏

    2019-07-13 21:39:22
    内存泄漏 当系统运行到某一时刻,某些占用着一定内存空间的操作或对象在之后都不会使用了,所以此时系统理应将这些内存空间给释放掉给接下来的系统运行使用,但是因为一些特殊的原因,从而导致这部分的内存空间一直...

    前提

    内存泄漏

    当系统运行到某一时刻,某些占用着一定内存空间的操作或对象在之后都不会使用了,所以此时系统理应将这些内存空间给释放掉给接下来的系统运行使用,但是因为一些特殊的原因,从而导致这部分的内存空间一直无法释放,而这些无法释放的内存空间就会一直无法有效的被系统利用,俗称占着茅坑不拉屎,这一现象称之为内存泄漏。

    危害:一次内存泄漏并不会导致太大的问题,但如果不断累积多次内存泄漏,那么系统内存空间中的不可在被利用的内存将会越来越多,而可重复利用的内存越来越少,最终导致系统无法在从内存空间中申请内存运行程序,系统也就会报内存溢出(OOM)异常。

    Java内部类和匿名内部类

    Java语法中,如果在某个类中定义了非静态的内部类或者匿名内部类,那么这些非静态的内部类或者匿名内部类的实例对象必定会隐式的强引用其外部类的实例对象。

    例子:

    	public class Other {
    	}
    	public class Outer {
    	
    	    // 非静态的内部类
    	    public class Inner {
    	        public String publicString = "Inner.publicString";
    	    }
    	
    	    public Inner getInner(){
    	        // new Inner()创建的对象内部必定持有Outer类的一个实例对象
    	        return new Inner();
    	    }
    	
    	    // 非静态的匿名内部类的对象,其内部必定持有Outer类的一个实例对象
    	    public Other other = new Other(){
    	        public void fun(){};
    	    };
    	
    	    public Other getOther(){
    	        return other;
    	    }
    	
    	    public Other getOthers(){
    	        // 非静态的匿名内部类的对象,其内部必定持有Outer类的一个实例对象
    	        Other other = new Other(){
    	            public void fun(){};
    	        };
    	        return other;
    	    }
    	}
    
    	Outer outer = new Outer();
    			
    	// inner1对象内部必定隐式的持有outer对象
    	Outer.Inner inner1 = outer.new Inner();
    	// inner2对象内部必定隐式的持有outer对象
    	Outer.Inner inner2 = outer.getInner();
    	
    	// other1对象内部必定隐式的持有outer对象
    	Other other1 = outer.getOther();
    	// other2对象内部必定隐式的持有outer对象
    	Other other2 = outer.getOthers();
    

    要想消除非静态的内部类或者匿名内部类的实例对象隐式的强引用其外部类的实例对象,只有将这些内部类或者匿名内部类声明为静态的内部类或者匿名内部类。

    例子:

    	public class Other {
    	}
    	public class Outer {
    	
    	    // 静态的内部类
    	    static public class Inner {
    	        public String publicString = "Inner.publicString";
    	    }
    	
    	    public Inner getInner(){
    	        return new Inner();
    	    }
    	
    	    // 静态的匿名内部类的对象
    	    public static Other other = new Other(){
    	        public void fun(){};
    	    };
    	
    	    public Other getOther(){
    	        return other;
    	    }
    	}
    	
    	Outer.Inner inner1 = new Outer.Inner();
    	
    	Outer outer = new Outer();
    	Outer.Inner inner2 = outer.getInner();
    
    	Other other1 = outer.getOther();
    

    Handler 内存泄漏的原因

    原因一

    Handler对象如果发送过消息,那么在消息被释放前,Handler对象就一定不会被GC回收

    	Handler myHandler = new Handler(){
    		@Override
    		public void handleMessage(Message msg) {
    			super.handleMessage(msg);
    		}
    	};
    	Message message = Message.obtain();
    	
    	myHandler.sendEmptyMessage(1);
    	myHandler.sendEmptyMessageAtTime(1,System.currentTimeMillis()+1000);
    	myHandler.sendEmptyMessageDelayed(1,1000);
    	
    	myHandler.sendMessage(message);
    	myHandler.sendMessageAtTime(message,System.currentTimeMillis()+1000);
    	myHandler.sendMessageDelayed(message,1000);
    	myHandler.sendMessageAtFrontOfQueue(message);
    	
    	Runnable runnable = new Runnable(){
    	    @Override
    	    public void run() {}
    	};
    	myHandler.post(runnable);
    	myHandler.postAtTime(runnable,System.currentTimeMillis()+1000);
    	myHandler.postAtTime(runnable,new Object(),System.currentTimeMillis()+1000);
    	myHandler.postDelayed(runnable,1000);
    	myHandler.postDelayed(runnable,new Object(),1000);
    	myHandler.postAtFrontOfQueue(runnable);
    	
    	// 以上Handler对象的所有发送消息的方法内部最后都会调用Hander对象的enqueueMessage()私有方法
    	// 即使是post发送,其内部最后也会自定义一个Message对象,然后将Runnable对象作为Message对象的callback属性的值
    	// enqueueMessage()方法的参数一是:Handler对象在创建时通过当前线程的Looper循环器对象获取到的MessageQueue消息队列对象
    	// enqueueMessage()方法的参数二是:Handler对象准备发送的Message消息对象
    	private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    		// 将当前发送消息的Handler对象的地址值赋值给被发送的Message消息对象的target变量
    		// 如此被发送的Message消息对象就强引用了发送它的Handler对象
    		msg.target = this;
    		if (mAsynchronous) {
    			msg.setAsynchronous(true);
    		}
    		// 最后会调用MessageQueue消息队列对象的enqueueMessage()方法
    		// 将已经处理好的Message消息对象添加进MessageQueue消息队列对象
    		// MessageQueue消息队列对象内部会强引用刚添加的Message消息对象
    		return queue.enqueueMessage(msg, uptimeMillis);
    	}
    

    从上面的代码可以看出,Handler对象被其发送的Message消息对象强引用,而被发送的Message消息对象被与所在线程绑定的MessageQueue消息队列对象强引用。

    因为在Java中一个对象要想被GC回收,那么这个对象就一定不可以有被强引用的情况,所以被Message消息对象强引用的Handler对象,就一定无法被GC回收,而如果想要Handler对象可以被GC回收,那么Handler对象去除被Message消息对象强引用的状态就是一个前提。

    如何取消Handler对象Message消息对象强引用的状态呢?其实Message消息对象会自动取消对Handler对象的强引用,但这个自动消除会在一个特定的时间。

        public static void loop() {
            final Looper me = myLooper();
            if (me == null) {
                throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
            }
            final MessageQueue queue = me.mQueue;
    		// 。。。。。。
            for (;;) {
                Message msg = queue.next(); // might block
                if (msg == null) {
                    // No message indicates that the message queue is quitting.
                    return;
                }
    			// 。。。。。。
                try {
                    msg.target.dispatchMessage(msg);
                    dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
                } finally {
                    if (traceTag != 0) {
                        Trace.traceEnd(traceTag);
                    }
                }
    			// 。。。。。。
    			// Message消息对象自行释放自身所有资源,回归消息池
    			// 其中也会去除对Handler对象的强引用
                msg.recycleUnchecked();
            }
        }
    

    从上面的代码可以看出,当Message消息对象MessageQueue消息队列对象中取出,并成功调用Message消息对象身上强引用的Handler对象dispatchMessage()方法后(dispatchMessage()方法内部会执行Handler对象handleMessage()方法或者执行post()方法传入的Runable对象的run()方法),Message消息对象会自动取消对Handler对象的强引用,也就是说只有当Handler对象执行了 之前所发消息次数 的dispatchMessage()方法,才有可能可以被GC回收(因为Handler对象有可能会被开发者主动强引用给别人)。

    原因二

    Handler对象中有可能会强引用了Activity对象

    Handler对象中为什么要引用Activity对象

    1. Handler的主要用途就是线程间通信。例如:我们在主线程中创建了一个重写handleMessage()方法Handler对象后,在去开启一个子线程,我们就可以在子线程中国通过调用之前在主线程中创建的Handler对象的发送消息的方法将消息发送到主线中。
    2. 而我们经常使用Handler的线程间通信功能的情景是:在Activity界面中开启子线程获取数据,然后将数据发送到主线程中,在主线程中根据数据来更新Activity界面中的控件,而其中的数据只有在Handler对象handleMessage()方法的方法体中才能获取到,所以更新Activity界面中的控件也只能在handleMessage()方法的方法体中实现,从而Handler对象也就必须引用Activity界面的实例对象,如此我们才能在handleMessage()方法的方法体中通过Activity界面的实例对象获得想要更新的控件对象。

    为了在Handler对象中引用Activity界面的实例对象,我们一般会重新定义一个继承Handler的类:

    	// 一般这个自定义Handler会声明在Activity类中,作为内部类
        class MyHandler extends Handler{
    		
    		private Activity activity;
    		
            MyHandler(Activity activity) {
                super();
                this.activity = activity;
            }
    
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
            }
        }
    	// 或者在Activity类中声明一个Handler匿名内部类对象
    	private Handler handler = new Handler(){
    		@Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Activity activity = Activity.this;
            }
    	}; 
    

    从上面的代码中我们可以看出,根据非静态的自定义Handler类或者Handler匿名类创建的Handler对象中有两处强引用Activity对象

    1. 因为自定义Handler类或者Handler匿名类是非静态声明,所以其类的实例对象必定隐式的强引用(非静态的自定义Handler类或者Handler匿名内部类声明所在的) Activity实例对象。
    2. 为了在handleMessage()方法中可以使用Activity实例对象,所以主动的强引用Activity实例对象。

    根据上面的两个原因,我们也就可以得出在Activity中使用Handler时,出现内存泄漏的情景:
    在一个Activity类中,开发者声明了一个非静态的自定义Handler类或者自定义Handler匿名类,并且在自定义的Handler类的构造函数或者handleMessage()方法中主动强引用Activity类的对象。当这个Activity界面被开启时,开发者又根据自定义的Handler类创建了Handler实例对象。接着在某一时刻开发者又拿着Handler实例对象多次发送各种延时或不延时的消息,同时又立即关闭了Activity界面。本来在Activity界面关闭时,对应的Activity对象的所有引用应该断开,等待GC回收这个Activity对象,但是因为在界面关闭时Activity对象在Handler对象中依然存在强引用,且Handler对象在其之前发送的所有消息被释放前,其依然会被部分消息强引用,所以GC如果在 Handler对象之前发送的所有消息被释放 之前启动回收,那么此时Handler对象必定无法被GC回收,从而Handler对象中对Activity对象的强引用也就无法断开,从而GC也就无法回收依然有着强引用的Activity对象。如此就造成了内存泄漏。

    解决Handler内存泄漏

    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    
    import java.lang.ref.WeakReference;
    
    public class MyActivity extends Activity {
    
        // 使用静态声明自定义Handler类,如此Activity界面关闭时,
        // 对应的Activity对象就不会在Handler对象中被强引用了
        static class MyHandler extends Handler{
    
            private final WeakReference<Activity> activity;
    
            public MyHandler(Activity activity) {
                super();
                // 使用弱引用接收Activity实例对象,如此Activity界面关闭时,
                // 对应的Activity对象就不会在Handler对象中被强引用了
                this.activity = new WeakReference<>(activity);
            }
    
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                // 注意在此处,最好不要在定义一个变量强引用activity.get()返回的Activity对象了
                // 而是直接将activity.get()当作一个Activity对象的变量名使用
                // 因为如果GC回收时,正好有一个消息从消息队列中取出,
                // 并执行了本方法,那么Activity对象立马又有了一个强引用,从而导致GC又无法回收Activity对象
                activity.get();
            }
        }
    
        private Handler handler = new MyHandler(MyActivity.this);
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
    
    
        @Override
        protected void onDestroy() {
            // 在Activity界面销毁时,在本界面中创建的Handler对象也就没有什么用处了
            // 且Handler对象之前发送的消息,即使之后会被Handler对象的handleMessage方法接收也没有必须继续执行下去了
            // 所以为了让Handler对象在Activity界面关闭后尽早被回收,就需要将Handler对象被消息强引用的状态给主动去除
            // 那么我们可以将Handler对象之前发送的消息都从消息队列中移除,如此Handler对象之前发送的消息都将得到释放
            // Handler对象也就不在被消息对象所引用了
    
            // 下面的代码的意思是去除消息队列中所有 target属性的值是handler对象并且what属性的是0的 消息
    
            // 之所以removeMessages方法的参数是0,是因为handler对象通过post发送Runnable对象时其内部也创建了消息对象,
            // 且没有设置消息对象的what属性的值,而what属性的值的初始值为0,
            // 而当handler对象通过send发送消息时,只要不对消息对象的what属性设置值
            // 那么handler对象发送的所有消息对象的what属性值则必定都是0。
    
            // Handler对象也可以使用removeCallbacksAndMessages(null)方法来移除所有之前发送的消息
            handler.removeCallbacksAndMessages(null);
            handler.removeMessages(0);
            super.onDestroy();
        }
    }
    
    展开全文
  • handler 内存泄漏

    2018-02-09 20:12:36
    Handler 消息机制用于主线程和子线程...使用率非常高,然而handler存在着内存泄漏。通常大家的写法是如下public class TestActivity extends Activity { .......  Handler handler = new Handler(){ @Override ...
  • Handler内存泄露

    2016-01-12 15:58:10
    Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收。也就是说,一个对象不被任何引用所指向,则该对象会在被GC发现的...
  • 所以这里来再次总结下为了防止Handler内存泄漏有哪些手段? 文章目录1. Handler为什么会造成内存泄漏?2. 预防Handler内存泄漏?2.1 使用静态Handler2.2 清空消息队列2.3 使用静态Handler+弱引用WeakReference3. ...
  • 在android开发过程中,我们可能会遇到过令人奔溃的OOM异常,这篇文章主要介绍了Android Handler内存泄漏详解及其解决方案,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 1. 说Handler内存泄露这种文章挺多的,基本就是handler 使用不当 持有外部引用导致的内存泄露完毕. 2.根据可达性gc 算法,当一个引用没有被root 对象引用时,该对象内存随时被系统回收,那么handler 的引用链又是...
  • 一、Handler内存泄漏原因 handler发送的消息在当前handler的消息队列中,如果此时activity finish掉了,那么消息队列的消息依旧会由handler进行处理,若此时handler声明为内部类(非静态内部类),我们知道内部类...
  • Android 解决Handler内存泄漏问题前言更多描述解决方法自定义弱引用Handler创建BaseActivity继承使用完事 前言 最近在维护老项目的时候发现,使用handler延时处理的事件再activity结束后仍旧再执行,导致activity...
  • 14.Android 控制Handler内存泄露 技巧

    千次阅读 2015-09-21 13:47:35
    Android 控制Handler内存泄露 技巧Android 控制Handler内存泄露 技巧 Handler 警告 Handler 内存泄露缘由 解决思路 Handler 通用模板 Handler 警告 In Android, Handler classes should be static or leaks might ...
  • 安卓handler内存泄漏分析及解决
  • Handler内存泄漏分析及解决
  • Android Context内存泄漏的情况很多,有兴趣可阅读以下文章: Android学习系列(36)--App调试内存...下面是关于Handler内存泄漏的一种解决方法: 1、将Handler声明为静态类; 2、在Handler中增加一个对Activity的
  • Handler内存泄露原理及解决方法
  • 主要给大家介绍了关于iOS WKWebView中MessageHandler内存泄漏问题的完美解决过程,文中通过示例代码介绍的非常详细,对各位iOS开发者们具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 从GCRoot角度来分析Handler 内存泄漏 文章目录引言开始分析handler是怎么持有Activity引用的handler是怎么发生内存泄漏的总结解决办法 引言 看了好多博客发现都只说了handler会有内存泄漏风险,原因是handler持有了...
  • Handler内存泄漏简析

    2017-03-01 14:09:06
    在Android开发过程中,我们可能会遇到过令人奔溃的OOM异常,面对这样的异常我们是既熟悉又深恶痛绝的,因为造成OOM的原因有很多种情况...1.Handler内存泄漏例子说明以及原理阐明 2.问题验证(如果感觉繁琐请直接跳过)
  • 防止handler内存泄漏

    2016-05-21 13:54:00
    handler为什么会内存泄漏呢,handler是个内部类,内部类会持有外部类的引用,内部类需要依赖外部类。handler需要定义为静态类,当你推出Activity,handler还在工作, 下面是引起内存溢出的:Activity已经finish,但...
  • Handler内存泄露的原因是什么? 你会怎么答呢? 这是错误的回答 "内部类持有了外部类的引用,也就是Hanlder持有了Activity的引用,从而导致无法被回收呗。" 其实这样回答是错误的,或者说没回答到点子上。 内存...
  • Handler内存泄露的原因是什么? 你会怎么答呢? 这是错误的回答 有的朋友看到这个题表示,就这?太简单了吧。 “内部类持有了外部类的引用,也就是Hanlder持有了Activity的引用,从而导致无法被回收呗。” 其实这样...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 39,740
精华内容 15,896
关键字:

handler内存泄漏