티스토리 뷰
Handler 에 대해 찾다가 Message 객체를 얻어오는 두 메소드를 알게 되었다.
무언가 다른 점이 있을것 같아 찾아본 내용들에 대해서 정리하고자 한다.
Message.obtain()
Android Developers 에서 찾아보면 이렇게 정의되어있다.
obtain
static fun obtain(): Message!
Return a new Message instance from the global pool. Allows us to avoid allocating new objects in many cases.
Global Message Pool 에서 새 Message 인스턴스를 반환한다. 많은 경우 새로운 객체의 할당을 피할 수 있다.
Global Message Pool
나는 정의를 보면서 global message pool 이 무엇인지가 궁금했는데, Message.java 코드를 살펴보면 알 수 있다.
private static Message sPool; // Message pool
private static final int MAX_POOL_SIZE = 50; // Message pool max size
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
sPoolSize--;
return m;
}
}
return new Message();
}
코드를 보면 단순히 Message class 내의 재활용되는 정적 메시지 객체이다.
그런데 13번 라인을 보면 sPool == null
일 때, 새 Message 객체를 생성하여 리턴하는데 일반적으로 알고있는 싱글턴과 다르게 설계되어있다. 이는 Message.recycle() 을 보면 알 수 있다.
/**
* Return a Message instance to the global pool. You MUST NOT touch
* the Message after calling this function -- it has effectively been
* freed.
*/
public void recycle() {
clearForRecycle();
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
위 메소드를 통해 메시지 인스턴스를 global message pool 에 되돌린다.
recycle()
은 Handler.dispatchMessage(Message msg) 가 한 번 호출되고 난 뒤에 호출된다고 한다.
Handler.dispatchMessage(Message msg)
Looper.loop() 에서 MessageQueue 에서 Message 를 가져와 msg.target.dispatchMessage(msg) 를 호출하여 Message 를 처리한다. ( tartget = handler )
자세한 내용은 Handler, Looper 의 구조에 대해 추가 포스팅하려 한다.
그럼 Message.obtain() 에 대해서 간략히 보았고 다음은 Handler.obtainMessage() 에 대해 보면서 서로 간 차이점을 점층적으로 분석해 보자.
Handler.obtainMessage()
마찬가지로 Android Developers 문서를 보자.
obtainMessage
public final Message obtainMessage()
Returns a new
Message
from the global message pool. More efficient than creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this). If you don't want that facility, just call Message.obtain() instead.Global Message Pool 에서 새 Message 를 반환한다. 새 인스턴스를 생성하고 할당하는 것 보다 더 효율적이다. 검색된 Message 에는 Message 의 Hander 가 설정되어있다. (Message.target == this) 만약 그것을 원하지 않는다면 Message.obtain() 을 대신 사용하라.
이것 또한 global message pool 에서 새 message 객체를 반환한다고 설명하고 있다.
코드 상에서 다른 점을 살펴보자.
public final Message obtainMessage()
{
return Message.obtain(this);
}
Handler.obtainMessage() 에서 Message.obtain() 의 결과를 리턴하고 있는걸 볼 수 있다.
this 로 Handler 자신을 파라미터로 넘겨주고 있는데, 이번에는 Message.obtain(Handelr handler) 의 코드를 보자.
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;
return m;
}
Message.obtain() 으로 가져온 Message 객체에 target handler 를 전달 받은 handler 로 지정하는 것을 볼 수 있다.
이 코드를 보고 나니 Android Developers 문서 설명이 이해가 된다.
검색된 Message 에는 Message 의 Handler 가 설정되어있다.
이제 알게된 내용을 정리해보자. Message.obtain(), Handler.obtainMessage() 모두 global Message Pool 에서 재활용 되는 새 Message 객체를 받아온다.
다른 점은 Handler.obtainMessage() 는 호출하는 Handler 로 target hander 가 지정된 Message 객체가 반환 된다는 것이다.
그런데 target handler 가 지정되면 무엇이 다른거지 ?
또 다시 구글링해보자.
obtain obtainMessage 를 키워드로 검색해 보았지만 좋은 글은 찾지 못하였다.
분석해 놓은 글을 하나 찾았지만 명확히 이해가 되지 않았고 참고를 위해 적어 두어야겠다.
검색결과 많은 의견이 Handler.obtainMessage() 를 쓰라는 것이 많았다.
이유에 대해서는 추후 더 조사해보도록 해야겠다.
References
http://androidxref.com/4.4.2_r1/xref/frameworks/base/core/java/android/os/Message.java#106
https://developer.android.com/reference/kotlin/android/os/Message?hl=en#obtain()
'프로그래밍 > Android' 카테고리의 다른 글
[Android] getLocationOnScreen vs getLocationInWindow() (1) | 2020.01.19 |
---|---|
[Android] Architecture Components 사용 시의 5가지 일반적인 실수 (0) | 2019.10.20 |
[Android] Handler ( sendMessage, post ) / runOnUiThread (1) | 2019.10.03 |
[Android] 인터페이스 상수 (0) | 2019.08.25 |
[Android] JNI (0) | 2019.08.25 |