programing

Android에서 Looper, Handler 및 MessageQueue의 관계는 무엇입니까?

nasanasas 2020. 8. 29. 11:11
반응형

Android에서 Looper, Handler 및 MessageQueue의 관계는 무엇입니까?


Looper, Handler및에 대한 공식 Android 문서 / 가이드를 확인했습니다 MessageQueue. 그러나 나는 그것을 얻을 수 없었다. 나는 안드로이드를 처음 접했고 이러한 개념과 매우 혼동되었습니다.


A Looper는 메시지 처리 루프입니다.에서 항목을 읽고 처리합니다 MessageQueue. Looper클래스는 일반적으로 HandlerThread(의 하위 클래스 Thread) 와 함께 사용됩니다 .

A HandlerLooper주로 메시지와 Runnable객체를 스레드의 에 게시 하여 a와의 상호 작용을 용이하게하는 유틸리티 클래스입니다 MessageQueue. Handler가 생성 되면 특정 Looper(및 관련 스레드 및 메시지 대기열)에 바인딩됩니다 .

일반적인 사용에서는를 만들고 시작한 HandlerThread다음 Handler다른 스레드가 HandlerThread인스턴스 와 상호 작용할 수 있는 개체 (또는 개체) 를 만듭니다 . 은 ( Handler는)에서 실행하는 동안 만들어야 HandlerThread하지만 일단 생성되면 Handler의 스케줄링 방법 ( post(Runnable)등)을 사용할 수있는 스레드에 대한 제한이 없습니다 .

Android 애플리케이션의 기본 스레드 (일명 UI 스레드)는 애플리케이션 인스턴스가 생성되기 전에 핸들러 스레드로 설정됩니다.

수업 문서 외에도 여기 에이 모든 것에 대한 좋은 토론이 있습니다 .

추신 위에 언급 된 모든 클래스는 패키지에 android.os있습니다.


안드로이드의 메인 스레드아닌 스레드에서 UI 구성 요소를 직접 업데이트 하는 것은 불법이라는 것은 널리 알려져 있습니다. 이 안드로이드 문서 ( UI 스레드에서 비용이 많이 드는 작업 처리)비용이 많이 드는 작업 을 수행하기 위해 별도의 스레드를 시작하고 완료된 후 UI를 업데이트 해야하는 경우 따라야 할 단계를 제안합니다 . 아이디어는 메인 스레드 와 관련된 Handler 객체 를 생성하고 적절한 시간에 Runnable게시하는 것입니다. 이것은 메인 스레드 에서 호출됩니다 . 이 메커니즘은 LooperHandler 클래스로 구현됩니다 .Runnable

Looper클래스는 유지 MessageQueue가 목록에 포함, 메시지를 . Looper의 중요한 특징은 그것이 생성 된 스레드연관 되어 있다는 것 입니다 . 이 연결은 영원히 유지 되며 깨지거나 변경할 수 없습니다. 또한 스레드가 있습니다 이상과 연관 될 수없는. 이 연결을 보장하기 위해 스레드 로컬 저장소에 저장되며 생성자를 통해 직접 생성 할 수 없습니다. 이를 만드는 유일한 방법은에서 정적 메서드 준비 를 호출 하는 것입니다 . 준비 메소드는 먼저 ThreadLocal을 검사합니다.LooperLooperLooperLooper스레드와 연관된 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 ]를 참조하십시오.

여기에 이미지 설명 입력

참고 URL : https://stackoverflow.com/questions/12877944/what-is-the-relationship-between-looper-handler-and-messagequeue-in-android

반응형