How/when is a Handler garbage collected?

后端 未结 3 1803
闹比i
闹比i 2021-02-12 16:26

Inside a class of mine I have the following code:

mHandler = createHandler();

private Handler createHandler() {
    return new Handler() {
        public void h         


        
相关标签:
3条回答
  • 2021-02-12 16:41

    No, stop sending message doesn't make GC work. As the doc points out, it bounds to the thread which creating it. If thread is running, the handler won't be recycled by GC.

    Why do you think this could cause memory leaking? What do you mean by "implicit reference to the enclosing Object"?

    0 讨论(0)
  • 2021-02-12 16:58

    In my specific example since the Handler is an anonymous inner class it has an implicit reference to the enclosing Object and the whole hierarchy of objects that is pointed by it.

    You could reduce the impact of the potential leak to almost nothing by using a static nested class instead of an anonymous inner class.

    0 讨论(0)
  • 2021-02-12 17:03

    An examination of the Handler source reveals more details.

    Here is some debug code from the Handler() constructor that was added by Romain Guy:

    if (FIND_POTENTIAL_LEAKS) {
      final Class<? extends Handler> klass = getClass();
      if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
          (klass.getModifiers() & Modifier.STATIC) == 0) {
        Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
          klass.getCanonicalName());
      }
    }
    

    The warning is clear: Don't declare your Handler subclass as an inner class.

    The Handler's looper is obtained from a static ThreadLocal instance:

    mLooper = Looper.myLooper();
    
    /**
     * Return the Looper object associated with the current thread.  Returns
     * null if the calling thread is not associated with a Looper.
     */
    public static final Looper myLooper() {
        return (Looper)sThreadLocal.get();
    }
    

    Anatomy of the leak:

    The main app thread retains the Looper and its MessageQueue, the Messages in the queue retain a link to their target Handler, and the Handler -- unless it is a static nested class with a WeakReference to your Activity -- will retain your Activity and its views.

    You could instead try to plug this leak by cleaning up your messages:

    handler.removeMessages(what);
    

    but this is easier said than done.

    Also see On Memory Leaks in Java and in Android

    0 讨论(0)
提交回复
热议问题