Android에서 Looper, Handler 및 MessageQueue의 관계는 무엇입니까?
Looper
, Handler
및에 대한 공식 Android 문서 / 가이드를 확인했습니다 MessageQueue
. 그러나 나는 그것을 얻을 수 없었다. 나는 안드로이드를 처음 접했고 이러한 개념과 매우 혼동되었습니다.
A Looper
는 메시지 처리 루프입니다.에서 항목을 읽고 처리합니다 MessageQueue
. 이 Looper
클래스는 일반적으로 HandlerThread
(의 하위 클래스 Thread
) 와 함께 사용됩니다 .
A Handler
는 Looper
주로 메시지와 Runnable
객체를 스레드의 에 게시 하여 a와의 상호 작용을 용이하게하는 유틸리티 클래스입니다 MessageQueue
. Handler
가 생성 되면 특정 Looper
(및 관련 스레드 및 메시지 대기열)에 바인딩됩니다 .
일반적인 사용에서는를 만들고 시작한 HandlerThread
다음 Handler
다른 스레드가 HandlerThread
인스턴스 와 상호 작용할 수 있는 개체 (또는 개체) 를 만듭니다 . 은 ( Handler
는)에서 실행하는 동안 만들어야 HandlerThread
하지만 일단 생성되면 Handler
의 스케줄링 방법 ( post(Runnable)
등)을 사용할 수있는 스레드에 대한 제한이 없습니다 .
Android 애플리케이션의 기본 스레드 (일명 UI 스레드)는 애플리케이션 인스턴스가 생성되기 전에 핸들러 스레드로 설정됩니다.
수업 문서 외에도 여기 에이 모든 것에 대한 좋은 토론이 있습니다 .
추신 위에 언급 된 모든 클래스는 패키지에 android.os
있습니다.
안드로이드의 메인 스레드 가 아닌 스레드에서 UI 구성 요소를 직접 업데이트 하는 것은 불법이라는 것은 널리 알려져 있습니다. 이 안드로이드 문서 ( UI 스레드에서 비용이 많이 드는 작업 처리) 는 비용이 많이 드는 작업 을 수행하기 위해 별도의 스레드를 시작하고 완료된 후 UI를 업데이트 해야하는 경우 따라야 할 단계를 제안합니다 . 아이디어는 메인 스레드 와 관련된 Handler 객체 를 생성하고 적절한 시간에 Runnable 을 게시하는 것입니다. 이것은 메인 스레드 에서 호출됩니다 . 이 메커니즘은 Looper 및 Handler 클래스로 구현됩니다 .Runnable
Looper
클래스는 유지 MessageQueue가 목록에 포함, 메시지를 . Looper의 중요한 특징은 그것이 생성 된 스레드 와 연관 되어 있다는 것 입니다 . 이 연결은 영원히 유지 되며 깨지거나 변경할 수 없습니다. 또한 스레드가 있습니다 이상과 연관 될 수없는 일 . 이 연결을 보장하기 위해 스레드 로컬 저장소에 저장되며 생성자를 통해 직접 생성 할 수 없습니다. 이를 만드는 유일한 방법은에서 정적 메서드 준비 를 호출 하는 것입니다 . 준비 메소드는 먼저 ThreadLocal을 검사합니다.Looper
Looper
Looper
Looper
스레드와 연관된 Looper가 아직 없는지 확인하기 위해 현재 스레드의. 검사 후 새 파일 Looper
이 생성되어 ThreadLocal
. 를 준비한 후 루프 메서드를 Looper
호출 하여 새 메시지를 확인 하고 처리해야합니다.Handler
이름에서 알 수 있듯이 Handler
클래스는 주로 현재 스레드의 메시지를 처리 (추가, 제거, 발송)하는 역할을합니다 MessageQueue
. Handler
예는 스레드에 바인딩됩니다. 핸들러 스레드 간의 결합을 통해 달성 Looper
하고 MessageQueue
. A는 Handler
되고 항상에 바인딩Looper
하고, 이후에 바인딩 관련하는 thread 와 함께 Looper
. 와 달리 Looper
여러 Handler 인스턴스는 동일한 스레드에 바인딩 될 수 있습니다. 에서 post 또는 모든 메소드를 호출 할 때마다 Handler
새 메시지가 연결된 MessageQueue
. 메시지의 대상 필드는 현재 Handler
인스턴스 로 설정됩니다 . 때Looper
이 메시지를 수신하면 메시지 의 대상 필드에서 dispatchMessage 를 호출 하여 메시지가 처리 할 Handler 인스턴스로 다시 라우팅되지만 올바른 스레드에 있습니다. Looper
, Handler
및 간의 관계 MessageQueue
는 다음과 같습니다.
루퍼부터 시작하겠습니다. Looper가 무엇인지 이해하면 Looper, Handler 및 MessageQueue 간의 관계를 더 쉽게 이해할 수 있습니다. 또한 GUI 프레임 워크의 맥락에서 Looper가 무엇인지 더 잘 이해할 수 있습니다. 루퍼는 2 가지 일을하도록 만들어졌습니다.
1) Looper transforms a normal thread, which terminates when its run()
method returns, into something that runs continuously until Android app is running, which is needed in GUI framework (Technically, it still terminates when run()
method returns. But let me clarify what I mean, below).
2) Looper provides a queue where jobs to be done are enqueued, which is also needed in GUI framework.
As you may know, when an application is launched, the system creates a thread of execution for the application, called “main”, and Android applications normally run entirely on a single thread by default the “main thread”. But main thread is not some secret, special thread. It's just a normal thread that you can also create with new Thread()
code, which means it terminates when its run()
method returns! Think of below example.
public class HelloRunnable implements Runnable {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}
Now, let's apply this simple principle to Android app. What would happen if an Android app is run on a normal thread? A thread called "main" or "UI" or whatever starts application, and draws all UI. So, the first screen is displayed to users. So what now? The main thread terminates? No, it shouldn’t. It should wait until users do something, right? But how can we achieve this behavior? Well, we can try with Object.wait()
or Thread.sleep()
. For example, main thread finishes its initial job to display first screen, and sleeps. It awakes, which means interrupted, when a new job to do is fetched. So far so good, but at this moment we need a queue-like data structure to hold multiple jobs. Think about a case when a user touches screen serially, and a task takes longer time to finish. So, we need to have a data structure to hold jobs to be done in first-in-first-out manner. Also, you may imagine, implementing ever-running-and-process-job-when-arrived thread using interrupt is not easy, and leads to complex and often unmaintainable code. We'd rather create a new mechanism for such purpose, and that is what Looper is all about. The official document of Looper class says, "Threads by default do not have a message loop associated with them", and Looper is a class "used to run a message loop for a thread". Now you can understand what it means.
Let's move to Handler and MessageQueue. First, MessageQueue is the queue that I mentioned above. It resides inside a Looper, and that's it. You can check it with Looper class's source code. Looper class has a member variable of MessageQueue.
Then, what is Handler? If there is a queue, then there should be a method that should enable us to enqueue a new task to the queue, right? That is what Handler does. We can enqueue a new task into a queue(MessageQueue) using various post(Runnable r)
methods. That's it. This is all about Looper, Handler, and MessageQueue.
My last word is, so basically Looper is a class that is made to address a problem that occurs in GUI framework. But this kind of needs also can happen in other situations as well. Actually it is a pretty famous pattern for multi threads application, and you can learn more about it in "Concurrent Programming in Java" by Doug Lea(Especially, chapter 4.1.4 "Worker Threads" would be helpful). Also, you can imagine this kind of mechanism is not unique in Android framework, but all GUI frameworks may need somewhat similar to this. You can find almost same mechanism in Java Swing framework.
MessageQueue
: It is a low-level class holding the list of messages to be dispatched by a Looper
. Messages are not added directly to a MessageQueue
, but rather through Handler
objects associated with the Looper
.[3]
Looper
: It loops over a MessageQueue
which contains the messages to be dispatched. The actual task of managing the queue is done by the Handler
which is responsible for handling (adding, removing, dispatching) messages in the message queue.[2]
Handler
: It allows you to send and process Message
and Runnable
objects associated with a thread's MessageQueue
. Each Handler instance is associated with a single thread and that thread's message queue.[4]
When you create a new Handler
, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
이해를 돕기 위해 아래 이미지 [ 2 ]를 참조하십시오.
'programing' 카테고리의 다른 글
Linq to SQL "(값 목록)에서 [열] 위치"수행 방법 (0) | 2020.08.30 |
---|---|
Android에서 Webview의 글꼴을 변경하는 방법은 무엇입니까? (0) | 2020.08.29 |
Javascript / jQuery의 배열에서 여러 요소 제거 (0) | 2020.08.29 |
HTML 요소에서 끌어서 놓기를 비활성화 하시겠습니까? (0) | 2020.08.29 |
django : BooleanField, 기본값을 true로 설정하는 방법은 무엇입니까? (0) | 2020.08.29 |