티스토리 뷰

반응형

Stack Overflow에 자주 검색, 등록되는 문제들과 제가 개발 중 찾아 본 문제들 중에서 나중에도 찾아 볼 것 같은 문제들을 정리하고 있습니다.

Stack Overflow에서 가장 먼저 확인하게 되는 가장 높은 점수를 받은 Solution과 현 시점에 도움이 될 수 있는 가장 최근에 업데이트(최소 점수 확보)된 Solution을 각각 정리하였습니다.

 

아래 word cloud를 통해 이번 포스팅의 주요 키워드를 미리 확인하세요.

This Handler class should be static or leaks might occur: IncomingHandler

'This Handler class should be static or leaks might occur: IncomingHandler' 오류 수정하기

 문제 내용 

I'm developing an Android 2.3.3 application with a service. I have this inside that service to communicate with Main activity:

저는 서비스 안에서 MainActivity와 통신하기 위해 다음과 같이 구현하고 있는 안드로이드 2.3.3 애플리케이션을 개발 중입니다.
public class UDPListenerService extends Service
{
    private static final String TAG = "UDPListenerService";
    //private ThreadGroup myThreads = new ThreadGroup("UDPListenerServiceWorker");
    private UDPListenerThread myThread;
    /**
     * Handler to communicate from WorkerThread to service.
     */
    private Handler mServiceHandler;

    // Used to receive messages from the Activity
    final Messenger inMessenger = new Messenger(new IncomingHandler());
    // Use to send message to the Activity
    private Messenger outMessenger;

    class IncomingHandler extends Handler
    {
        @Override
        public void handleMessage(Message msg)
        {
        }
    }

    /**
     * Target we publish for clients to send messages to Incoming Handler.
     */
    final Messenger mMessenger = new Messenger(new IncomingHandler());
    [ ... ]
}

 

And here, final Messenger mMessenger = new Messenger(new IncomingHandler());, I get the following Lint warning:

그리고 여기서, final Messenger mMessenger = new Messenger(new IncomingHandler());, 저는 다음과 같은 Lint 경고를 받습니다:

 

This Handler class should be static or leaks might occur: IncomingHandler

 

What does it mean?

그것은 무엇을 의미하나요?

 

 

 

 높은 점수를 받은 Solution 

If IncomingHandler class is not static, it will have a reference to your Service object.

IncomingHandler 클래스가 static이 아니면 Service 객체에 대한 참조를 가지게 됩니다.

 

Handler objects for the same thread all share a common Looper object, which they post messages to and read from.

동일한 스레드에 대한 Handler 객체들은 모두 동일한 Looper 객체를 공유합니다. 이들은 메시지를 보내고 받는데 사용됩니다.

 

As messages contain target Handler, as long as there are messages with target handler in the message queue, the handler cannot be garbage collected. If handler is not static, your Service or Activity cannot be garbage collected, even after being destroyed.

메시지는 대상 핸들러(Target Handler)를 포함하므로, 메시지 큐에 대상 핸들러가 있는 한 핸들러는 가비지 컬렉션될 수 없습니다. 만약 핸들러가 static이 아니라면, Service나 Activity가 소멸되더라도 가비지 컬렉션될 수 없습니다.

 

This may lead to memory leaks, for some time at least - as long as the messages stay int the queue. This is not much of an issue unless you post long delayed messages.

이는 메시지 큐에 대상 핸들러가 있는 한 메모리 누수로 이어질 수 있습니다. 핸들러가 정적이지 않으면 서비스나 액티비티가 파괴된 후에도 가비지 컬렉션될 수 없습니다. 이는 메시지가 큐에 남아 있는 한 (메시지 큐에서 대기 중인) 일정 시간 동안 메모리 누수를 야기할 수 있습니다. 긴 지연 메시지를 게시하지 않는 한 큰 문제가 되지 않습니다.

 

You can make IncomingHandler static and have a WeakReference to your service:

IncomingHandler 클래스를 static으로 만들고 Service에 대한 WeakReference를 가질 수 있습니다.
static class IncomingHandler extends Handler {
    private final WeakReference<UDPListenerService> mService; 

    IncomingHandler(UDPListenerService service) {
        mService = new WeakReference<UDPListenerService>(service);
    }
    @Override
    public void handleMessage(Message msg)
    {
         UDPListenerService service = mService.get();
         if (service != null) {
              service.handleMessage(msg);
         }
    }
}

 

See this post by Romain Guy for further reference

추가 참고 자료로 로맹 가이(Romain Guy)의 이 게시물을 참조하세요.

 

 

 

 가장 최근 달린 Solution 

Here is a generic example of using a weak reference and static handler class to resolve the problem (as recommended in the Lint documentation):

Lint 문서에서 권장하는 대로, 약한 참조와 정적 핸들러 클래스를 사용하여 문제를 해결하는 일반적인 예시입니다.
public class MyClass{

  //static inner class doesn't hold an implicit reference to the outer class
  private static class MyHandler extends Handler {
    //Using a weak reference means you won't prevent garbage collection
    private final WeakReference<MyClass> myClassWeakReference; 

    public MyHandler(MyClass myClassInstance) {
      myClassWeakReference = new WeakReference<MyClass>(myClassInstance);
    }

    @Override
    public void handleMessage(Message msg) {
      MyClass myClass = myClassWeakReference.get();
      if (myClass != null) {
        ...do work here...
      }
    }
  }

  /**
   * An example getter to provide it to some external class
   * or just use 'new MyHandler(this)' if you are using it internally.
   * If you only use it internally you might even want it as final member:
   * private final MyHandler mHandler = new MyHandler(this);
   */
  public Handler getHandler() {
    return new MyHandler(this);
  }
}

 

 

출처 : https://stackoverflow.com/questions/11407943/this-handler-class-should-be-static-or-leaks-might-occur-incominghandler

반응형
댓글
공지사항
최근에 올라온 글