Looper의 목적은 무엇이며 어떻게 사용합니까?


454

저는 Android를 처음 사용합니다. Looper수업이 무엇을하고 어떻게 사용하는지 알고 싶습니다 . Android Looper 클래스 설명서를 읽었 지만 완전히 이해할 수는 없습니다. 나는 많은 곳에서 그것을 보았지만 그 목적을 이해할 수 없었다. 누구나 목적을 정의하고 Looper가능한 경우 간단한 예를 제시하여 나를 도울 수 있습니까?


7
방금 Looper에 대한 매우 철저하고 명확한 설명과 Safari Books Online에서의 사용법을 발견했습니다. 불행히도 제한된 시간 동안 만 무료로 액세스 할 수 있다고 의심됩니다. safaribooksonline.com/library/view/efficient-android-threading/…
Joe Lapp

1
Android 기사 및 참조 페이지에서는 현재 기사를 파악하기 전에 이전 기사를 이해하고 있어야합니다. Api guide의 Activity and Service 기사를 읽은 다음 Handler and Looper를 읽으십시오. 또한 스레드가 무엇인지 이해하는 데 도움이됩니다 (Android 스레드가 아니라 일반적으로 스레드 ... 예 : POSIX).
FutureSci

1
이 기사가 유용하다는 것을 알았습니다 : codetheory.in/…
Herman

답변:


396

루퍼 란?

루퍼는 큐에서 메시지 (실행 파일)를 실행하는 데 사용되는 클래스입니다. 일반 스레드에는 그러한 대기열이 없습니다. 예를 들어 단순 스레드에는 대기열이 없습니다. 메소드 실행이 한 번 실행되면 스레드가 다른 Message (Runnable)를 실행하지 않습니다.

Looper 클래스는 어디에서 사용할 수 있습니까?

누군가가 여러 메시지 (Runnables)를 실행하려면 스레드에서 대기열을 생성하는 Looper 클래스를 사용해야합니다. 예를 들어 인터넷에서 파일을 다운로드하는 응용 프로그램을 작성하는 동안 Looper 클래스를 사용하여 다운로드 할 파일을 대기열에 넣을 수 있습니다.

어떻게 작동합니까?

prepare()루퍼를 준비하는 방법 이 있습니다 . 그런 다음 사용할 수 있습니다loop() method를 사용하여 현재 스레드에서 메시지 루프를 작성할 있으며 이제 Looper는 루프를 종료 할 때까지 큐에서 요청을 실행할 준비가되었습니다.

루퍼를 준비 할 수있는 코드는 다음과 같습니다.

class LooperThread extends Thread {
      public Handler mHandler;

      @Override
      public void run() {
          Looper.prepare();

          mHandler = new Handler() {
              @Override
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };

          Looper.loop();
      }
  }

17
AsyncTask는 모든 스레드 관리를 캡슐화하므로 해당 목적에 더 적합하고 덜 복잡합니다.
Fernando Gallego

4
run () 및 handleMessage () 메소드 앞에 @Override 어노테이션이 있어야 함
Andrew Mackenzie

5
설명서에는 looper.quit를 호출해야한다고 표시되어 있습니다. 위 코드에서 Looper.loop는 무기한 차단됩니다.
AndroidDev

2
루프를 종료하는 방법. 위 코드 예제에서 Looper.quit ()를 어디에 포함시켜야합니까?
Seenu69

6
루 퍼가 있는 스레드에 편리한 클래스 인 HandlerThread 를 사용 하는 것이 좋습니다 .
Nimrod Dayan

287

GUI 프레임 워크와 관련하여 Looper가 무엇인지 더 잘 이해할 수 있습니다. 루퍼는 2 가지 일을하도록 만들어졌습니다.

1) Looper 는 GUI 프레임 워크에서 필요한 안드로이드 앱이 실행될 때까지 run () 메소드가 반환 될 때 종료 되는 일반 스레드를 연속적으로 실행되는 스레드로 변환합니다 (기술적으로 run () 메소드가 반환되면 종료됩니다). 아래에서 내가 의미하는 바를 분명히하십시오).

2) 루퍼 수행 할 작업 이 큐에 대기 되는 큐를 제공하며 , 이는 GUI 프레임 워크에도 필요합니다.

아시다시피, 응용 프로그램이 시작되면 시스템은 "main"이라는 응용 프로그램에 대한 실행 스레드를 만들고 Android 응용 프로그램은 일반적으로 기본적으로 "main thread"로 단일 스레드에서 완전히 실행됩니다. 그러나 메인 스레드는 비밀스럽고 특별한 스레드가 아닙니다 . new Thread()코드 로 만든 스레드와 비슷한 일반 스레드 이므로 run () 메서드가 반환되면 종료됩니다. 아래 예를 생각해보십시오.

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();
    }
}

이제이 간단한 원리를 Android 앱에 적용 해 봅시다. Android 앱이 일반 스레드에서 실행되면 어떻게 되나요? "main"또는 "UI"라는 스레드 또는 응용 프로그램을 시작하고 모든 UI를 그립니다. 따라서 첫 번째 화면이 사용자에게 표시됩니다. 그래서 지금 무엇? 메인 스레드가 종료됩니까? 아닙니다. 사용자가 무언가를 할 때까지 기다려야합니다. 그러나 우리는 어떻게이 행동을 달성 할 수 있습니까? 글쎄, 우리는 시도 할 수 있습니다Object.wait() 또는Thread.sleep(). 예를 들어, 메인 스레드는 첫 번째 화면을 표시하기 위해 초기 작업을 완료하고 휴면 상태입니다. 새로운 작업을 가져올 때 깨어납니다. 지금까지는 훌륭했지만 현재 여러 작업을 보유하려면 대기열과 유사한 데이터 구조가 필요합니다. 사용자가 화면을 직렬로 터치하는 경우를 생각해보고 작업을 완료하는 데 시간이 더 오래 걸립니다. 따라서 선입 선출 방식으로 작업을 수행 할 수있는 데이터 구조가 필요합니다. 또한 인터럽트를 사용하여 도착한 스레드를 항상 실행하고 처리하는 작업을 구현하는 것은 쉽지 않으며 복잡하고 유지 관리 할 수없는 코드로 이어질 수 있습니다. 우리는 오히려 그러한 목적을 위해 새로운 메커니즘을 만들고 싶습니다 . 이것이 바로 루퍼의 모든 것 입니다. 그만큼루퍼 클래스 공식 문서"기본적으로 스레드에는 이와 연관된 메시지 루프가 없습니다"라고 말하고 Looper는 "스레드에 대한 메시지 루프를 실행하는 데 사용되는"클래스입니다. 이제 그 의미를 이해할 수 있습니다.

더 명확하게하기 위해 메인 스레드가 변환되는 코드를 확인하십시오. 모든 것은 ActivityThread 클래스 에서 발생합니다 . main () 메소드에서 아래 코드를 찾을 수 있습니다.이 코드는 일반적인 메인 스레드를 필요한 것으로 변환합니다.

public final class ActivityThread {
    ...
    public static void main(String[] args) {
        ...
        Looper.prepareMainLooper();
        Looper.loop();
        ...
    }
}

Looper.loop()방법 무한 루프 및 시간에서 메시지 처리 한 디큐 :

public static void loop() {
    ...
    for (;;) {
        Message msg = queue.next(); // might block
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }
        ...
        msg.target.dispatchMessage(msg);
        ...
    }
}

따라서 기본적으로 Looper는 GUI 프레임 워크에서 발생하는 문제를 해결하기 위해 만들어진 클래스입니다. 그러나 이런 종류의 요구는 다른 상황에서도 발생할 수 있습니다. 실제로 이것은 다중 스레드 응용 프로그램에서 매우 유명한 패턴이며 Doug Lea의 " Java 동시 프로그래밍 "에서 자세히 배울 수 있습니다 (특히 4.1.4 "작업 스레드"가 도움이됩니다). 또한 이러한 종류의 메커니즘이 Android 프레임 워크에서 고유하지 않다고 생각할 수 있지만 모든 GUI 프레임 워크는 이와 비슷해야합니다. Java Swing 프레임 워크에서 거의 동일한 메커니즘을 찾을 수 있습니다.


26
이것은 실제로 Looper 클래스가 사용되는 이유에 대해 설명하는 유일한 대답입니다. 왜 이것이 최고 답변이 아닌지 잘 모르겠습니다. 세 등급이 높은 답변은 아무 것도 설명하지 않습니다.
Andrew Koster

4
@AK. 그래서 너무 늦게 보였지만이 답변을 추가했습니다. 내 대답이 도움이 되었기 때문에 기쁘다! :)
김준호

1
@ Hey-men-whatsup 예
김준호

1
이것을 읽기 전에 나는 "루퍼 ???" 이제 "오, 그래, 논의하자". 고마워, 좋은 답변 :)
umerk44

빠른 질문. 메인 스레드에서 모든 UI 요소를 가져온 후 잠자기 상태라고 언급했습니다. 그러나 사용자가 화면의 버튼과 상호 작용하고 버튼 클릭이 메인 대기열에 넣지 않더라도 일부 객체가 올바른 액티비티로 파견 한 다음 해당 액티비티의 메인 스레드가 깨어 실행됩니다 해당 버튼 클릭에 대한 콜백의 코드는 무엇입니까?
CapturedTree

75

루퍼를 사용하면 단일 스레드에서 작업을 순차적으로 실행할 수 있습니다. 그리고 handler는 실행해야 할 작업을 정의합니다. 이 예제에서 설명하려는 전형적인 시나리오입니다.

class SampleLooper extends Thread {
@Override
public void run() {
  try {
    // preparing a looper on current thread     
    // the current thread is being detected implicitly
    Looper.prepare();

    // now, the handler will automatically bind to the
    // Looper that is attached to the current thread
    // You don't need to specify the Looper explicitly
    handler = new Handler();

    // After the following line the thread will start
    // running the message loop and will not normally
    // exit the loop unless a problem happens or you
    // quit() the looper (see below)
    Looper.loop();
  } catch (Throwable t) {
    Log.e(TAG, "halted due to an error", t);
  } 
}
}

이제 다른 스레드 (ui 스레드)의 핸들러를 사용하여 작업을 Looper에 게시하여 실행할 수 있습니다.

handler.post(new Runnable()
{
public void run() {
//This will be executed on thread using Looper.
    }
});

UI 스레드에는 UI 스레드에서 메시지를 처리 ​​할 수있는 암시 적 Looper가 있습니다.


UI 프로세스를 잠그지 않습니다. 맞습니까?
gumuruh

4
큐에 "작업"을 게시하는 방법에 대한 예제를 포함하여 주셔서 감사합니다
피터 Lillevold

이것은 왜이 클래스를 사용하는지 설명하지 않고 어떻게 만 사용합니다.
Andrew Koster

33

Android Looper는 첨부 MessageQueue할 랩퍼 Thread이며 큐 처리를 관리합니다. 그것은 안드로이드 문서에서 매우 암호처럼 보이며 우리는 LooperUI 관련 문제에 직면 할 수 있습니다. 기본 사항을 이해하지 못하면 처리하기가 매우 어려워집니다.

여기입니다 기사 설명 Looper그것과의 사용을 사용하는 방법, 라이프 사이클 Looper에가Handler

여기에 이미지 설명을 입력하십시오

루퍼 = 스레드 + MessageQueue


3
이것은 왜이 클래스를 사용하는지 설명하지 않고 어떻게 만 사용합니다.
Andrew Koster

14

루퍼 및 핸들러의 정의 :

루퍼는 인로 스레드를 켤 수있는 클래스 파이프 라인 스레드 Handler 는 다른 스레드에서 작업을 스레드로 푸시하는 메커니즘을 제공합니다.

세부:

그래서 파이프 라인 스레드 는 처리기를 통해 다른 스레드에서 더 많은 작업을받을 수있는 스레드입니다.

루퍼 그것을 실행, 다음 작업 소요 그 다음 일 등을한다, - 그것은 루프를 구현하기 때문에 그렇게 이름이 지정됩니다. 처리기는 다른 스레드에서 매번 다음 작업을 처리하거나 수락하고 Looper (Thread 또는 PipeLine Thread)로 전달하는 데 사용되므로 처리기라고합니다.

예:

Looper and Handler 또는 PipeLine Thread의 가장 완벽한 예는 하나 이상의 이미지를 다운로드하거나 백그라운드에서 각 네트워크 호출에 대해 새 스레드를 시작하는 대신 단일 스레드에서 하나씩 서버 (Http)에 업로드하는 것입니다.

루퍼 및 핸들러와 파이프 라인 스레드의 정의에 대해 자세히 읽으십시오.

Android Guts : 루퍼 및 핸들러 소개


7

루퍼는 A가 들어synchronized MessageQueue 큐에 배치 프로세스 메시지에 사용되는 것을.

그것은 구현 Thread특정 스토리지 패턴을 .

Looper당 하나만 Thread. 주요 방법은 다음 과 같습니다 prepare().loop()quit() 입니다.

prepare()전류를 Thread로 초기화합니다 Looper. prepare()static용도 방법은 ThreadLocal아래와 같이 클래스.

   public static void prepare(){
       ...
       sThreadLocal.set
       (new Looper());
   }
  1. prepare() 이벤트 루프를 실행하기 전에 명시 적으로 호출해야합니다.
  2. loop()메시지가 특정 스레드의 메시지 대기열에 도착하기를 기다리는 이벤트 루프를 실행합니다. 다음 메시지가 수신되면 loop()메소드는 메시지를 대상 핸들러로 전달합니다.
  3. quit()이벤트 루프를 종료합니다. 루프를 종료하지 않고 대신 특별한 메시지를 대기열에 넣습니다.

LooperThread여러 단계를 통해 프로그래밍 가능

  1. 넓히다 Thread

  2. Looper.prepare()Thread를 초기화하기 위해 호출Looper

  3. 하나 이상의 Handler메시지를 작성하여 수신 메시지를 처리하십시오.

  4. Looper.loop()루프가 지시 될 때까지 메시지를 처리하기 위해 호출 합니다 quit().

5

메소드 완료 후 Java 스레드 의 수명 이 끝났습니다 run(). 동일한 스레드를 다시 시작할 수 없습니다.

루퍼 는 법선 Thread을 메시지 루프로 변환 합니다. 주요 방법 Looper은 다음 과 같습니다.

void prepare ()

현재 스레드를 루퍼로 초기화하십시오. 이를 통해 실제로 루프를 시작하기 전에이 루퍼를 참조하는 핸들러를 작성할 수 있습니다. 이 메소드를 호출 한 후 loop ()를 호출하고 quit ()를 호출하여 종료하십시오.

void loop ()

이 스레드에서 메시지 큐를 실행하십시오. 루프를 끝내려면 quit ()을 호출하십시오.

void quit()

루퍼를 종료합니다.

메시지 큐에서 더 이상 메시지를 처리하지 않고 loop () 메소드를 종료시킵니다.

Janishar 의이 mindorks 기사 는 핵심 개념을 잘 설명합니다.

여기에 이미지 설명을 입력하십시오

Looper스레드와 연관되어 있습니다. LooperUI 스레드 가 필요한 경우 Looper.getMainLooper()연결된 스레드를 반환합니다.

HandlerLooper 와 연결되어 있어야 합니다 .

Looper, HandlerHandlerThread비동기 프로그래밍의 문제를 해결하는 안드로이드의 방법입니다.

가 있으면 Handler아래 API를 호출 할 수 있습니다.

post (Runnable r)

Runnable r이 메시지 큐에 추가되도록합니다. 실행 가능 파일은이 핸들러가 연결된 스레드에서 실행됩니다.

boolean sendMessage (Message msg)

현재 시간 이전의 모든 보류중인 메시지 후에 메시지를 메시지 큐의 끝으로 푸시합니다. 이 핸들러에 첨부 된 스레드에서 handleMessage (Message)에 수신됩니다.

핸들러 스레드 는 있는 새 스레드를 시작하는 데 유용한 클래스입니다. 그런 다음 루퍼를 사용하여 핸들러 클래스를 작성할 수 있습니다.

일부 시나리오에서는 RunnableUI 스레드 에서 작업을 실행할 수 없습니다 . 네트워크 운영InputStream

이 경우 HandlerThread유용합니다. 메인 스레드 대신 Looper객체를 가져 HandlerThread오고 Handleron을 만들 수 있습니다 HandlerThread.

HandlerThread의 코드는 다음과 같이 될 것입니다 :

@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

예제 코드는 아래 게시물을 참조하십시오.

안드로이드 : 스레드 토스트


5

루퍼 스레드 이해

java 스레드는 run () 메소드에서 작업을 수행하고 그 후에 종료되도록 설계된 실행 단위입니다. 여기에 이미지 설명을 입력하십시오

그러나 안드로이드에는 스레드를 유지하고 사용자 입력 / 이벤트를 기다려야하는 많은 사용 사례가 있습니다. UI 스레드 일명Main Thread .

Android의 기본 스레드는 앱 시작시 JVM에 의해 처음 시작되고 사용자가 닫거나 처리되지 않은 예외가 발생할 때까지 계속 실행되는 Java 스레드입니다.

응용 프로그램이 시작되면 시스템은 "main"이라는 응용 프로그램에 대한 실행 스레드를 만듭니다. 이 스레드는 그리기 이벤트를 포함하여 적절한 사용자 인터페이스 위젯으로 이벤트를 전달해야하기 때문에 매우 중요합니다.

여기에 이미지 설명을 입력하십시오

이제 주요 스레드는 Java 스레드이지만 사용자 이벤트를 계속 듣고 화면에 60fps 프레임을 그리며 각 사이클 후에도 여전히 죽지 않습니다. 어때요?

정답은 Looper Class입니다 . Looper는 스레드를 활성 상태로 유지하고 해당 스레드에서 작업을 실행하기 위해 메시지 대기열을 관리하는 데 사용되는 클래스입니다.

스레드는 기본적으로 메시지 루프를 가지고 있지 않지만 run 메소드에서 Looper.prepare ()를 호출 한 다음 Looper.loop ()를 호출하여 스레드를 할당 할 수 있습니다.

루퍼의 목적은 스레드를 활성 상태로 유지하고 다음 입력주기를 기다리는 것입니다. Message 첫 번째 실행주기 후에 소멸되는 계산을 수행하기 오브젝트 것입니다.

Looper가 Message객체 큐를 관리하는 방법을 더 깊이 파고 싶다면 소스 코드를 살펴보십시오.Looperclass .

https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/os/Looper.java

다음은를 사용하여 클래스를 만들고 클래스 Looper Thread와 통신 하는 방법의 예입니다.ActivityLocalBroadcast

class LooperThread : Thread() {

    // sendMessage success result on UI
    private fun sendServerResult(result: String) {
        val resultIntent = Intent(ServerService.ACTION)
        resultIntent.putExtra(ServerService.RESULT_CODE, Activity.RESULT_OK)
        resultIntent.putExtra(ServerService.RESULT_VALUE, result)
        LocalBroadcastManager.getInstance(AppController.getAppController()).sendBroadcast(resultIntent)
    }

    override fun run() {
        val looperIsNotPreparedInCurrentThread = Looper.myLooper() == null

        // Prepare Looper if not already prepared
        if (looperIsNotPreparedInCurrentThread) {
            Looper.prepare()
        }

        // Create a handler to handle messaged from Activity
        handler = Handler(Handler.Callback { message ->
            // Messages sent to Looper thread will be visible here
            Log.e(TAG, "Received Message" + message.data.toString())

            //message from Activity
            val result = message.data.getString(MainActivity.BUNDLE_KEY)

            // Send Result Back to activity
            sendServerResult(result)
            true
        })

        // Keep on looping till new messages arrive
        if (looperIsNotPreparedInCurrentThread) {
            Looper.loop()
        }
    }

    //Create and send a new  message to looper
    fun sendMessage(messageToSend: String) {
        //Create and post a new message to handler
        handler!!.sendMessage(createMessage(messageToSend))
    }


    // Bundle Data in message object
    private fun createMessage(messageToSend: String): Message {
        val message = Message()
        val bundle = Bundle()
        bundle.putString(MainActivity.BUNDLE_KEY, messageToSend)
        message.data = bundle
        return message
    }

    companion object {
        var handler: Handler? = null // in Android Handler should be static or leaks might occur
        private val TAG = javaClass.simpleName

    }
}

사용법 :

 class MainActivity : AppCompatActivity() {

    private var looperThread: LooperThread? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // start looper thread
        startLooperThread()

        // Send messages to Looper Thread
        sendMessage.setOnClickListener {

            // send random messages to looper thread
            val messageToSend = "" + Math.random()

            // post message
            looperThread!!.sendMessage(messageToSend)

        }   
    }

    override fun onResume() {
        super.onResume()

        //Register to Server Service callback
        val filterServer = IntentFilter(ServerService.ACTION)
        LocalBroadcastManager.getInstance(this).registerReceiver(serverReceiver, filterServer)

    }

    override fun onPause() {
        super.onPause()

        //Stop Server service callbacks
     LocalBroadcastManager.getInstance(this).unregisterReceiver(serverReceiver)
    }


    // Define the callback for what to do when data is received
    private val serverReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            val resultCode = intent.getIntExtra(ServerService.RESULT_CODE, Activity.RESULT_CANCELED)
            if (resultCode == Activity.RESULT_OK) {
                val resultValue = intent.getStringExtra(ServerService.RESULT_VALUE)
                Log.e(MainActivity.TAG, "Server result : $resultValue")

                serverOutput.text =
                        (serverOutput.text.toString()
                                + "\n"
                                + "Received : " + resultValue)

                serverScrollView.post( { serverScrollView.fullScroll(View.FOCUS_DOWN) })
            }
        }
    }

    private fun startLooperThread() {

        // create and start a new LooperThread
        looperThread = LooperThread()
        looperThread!!.name = "Main Looper Thread"
        looperThread!!.start()

    }

    companion object {
        val BUNDLE_KEY = "handlerMsgBundle"
        private val TAG = javaClass.simpleName
    }
}

비동기 작업 또는 인 텐트 서비스를 대신 사용할 수 있습니까?

  • 비동기 작업은 백그라운드에서 짧은 작업을 수행하고 UI 스레드에 대한 결과 및 결과를 제공하도록 설계되었습니다. 비동기 작업에는 128 개 이상의 비동기 작업을 만들 없고 최대 5 개의 비동기 작업ThreadPoolExecutor 만 허용 할 수 있는 제한이 있습니다 .

  • IntentServices또한 약간 더 오랜 시간 동안 백그라운드 작업을 수행하도록 설계되었으며와 LocalBroadcast통신 하는 데 사용할 수 있습니다 Activity. 그러나 작업 실행 후 서비스가 파괴됩니다. 만약 당신이 오랫동안 실행을 유지하려는 경우보다 더 많은 일을해야합니다 while(true){...}.

루퍼 스레드에 대한 다른 의미있는 사용 사례 :

  • 서버가 클라이언트 소켓을 수신 대기하고 계속 확인 응답하는 양방향 소켓 통신에 사용됩니다.

  • 백그라운드에서 비트 맵 처리 이미지 URL을 Looper 스레드에 전달하면 필터 효과를 적용하여 임시 위치에 저장 한 다음 이미지의 임시 경로를 브로드 캐스트합니다.


4

이 답변은 질문과 관련이 없지만 루퍼의 사용과 사람들이 핸들러와 루퍼를 모든 방법으로 만든 방법은 일반적인 나쁜 습관입니다 (일부 설명은 정확하지만).이 글을 게시해야합니다.

HandlerThread thread = new HandlerThread(threadName);
thread.start();
Looper looper = thread.getLooper();
Handler myHandler = new Handler(looper);

그리고 완전한 구현을 위해


3

서비스 에서 여러 다운 또는 업로드 항목을 처리 하는 것이 더 좋은 예입니다.

Handler그리고 AsnycTask종종 전파하는 데 사용되는 이벤트 / 메시지 사이 UI (스레드) 및 작업자 스레드 또는 지연 행동을. 그래서 그들은 UI와 더 관련이 있습니다.

A Looper는 백그라운드에서 스레드 관련 대기열의 작업 ( Runnables, Futures )을 처리합니다. 사용자 상호 작용이나 표시된 UI가 없어도 (앱은 통화 중에 백그라운드에서 파일을 다운로드합니다).


1

루퍼 란?

문서에서

Looper

Looper에 대한 메시지 루프를 실행하는 데 사용되는 클래스 thread입니다. 스레드에는 기본적으로 메시지 루프가 없습니다. 하나를 만들려면 prepare()루프를 실행할 스레드를 호출 한 다음 loop()루프가 중지 될 때까지 메시지를 처리하도록합니다.

  • A Looper는 메시지 처리 루프입니다.
  • 루퍼의 중요한 특징은 루 퍼가 생성되는 스레드와 관련이 있다는 것입니다.
  • Looper 클래스 MessageQueue는 목록 메시지를 포함 하는를 유지 관리 합니다. 루퍼의 중요한 특징은 루 퍼가 생성되는 스레드와 관련이 있다는 것입니다.
  • Looper다음 작업을 소요, 그것을 실행, 그 다음 일 등을한다 - 그것은 루프를 구현하기 때문에 그렇게 이름이 지정됩니다. 그만큼Handler 사람이 더 좋은 이름을 발명하지 수 있기 때문에 핸들러를 호출
  • Android Looper는 Android 사용자 인터페이스 내의 Java 클래스로, Handler 클래스와 함께 버튼 클릭, 화면 다시 그리기 및 방향 스위치와 같은 UI 이벤트를 처리합니다.

어떻게 작동합니까?

여기에 이미지 설명을 입력하십시오

루퍼 만들기

스레드는 실행 후 LooperMessageQueue호출하여 호출 Looper.prepare()합니다. Looper.prepare()호출 스레드를 식별하고 Looper 및 MessageQueue오브젝트를 작성 하고 스레드를 연관시킵니다.

샘플 코드

class MyLooperThread extends Thread {

      public Handler mHandler; 

      public void run() { 

          // preparing a looper on current thread  
          Looper.prepare();

          mHandler = new Handler() { 
              public void handleMessage(Message msg) { 
                 // process incoming messages here
                 // this will run in non-ui/background thread
              } 
          }; 

          Looper.loop();
      } 
  }

자세한 내용은 아래 게시물을 확인하십시오.


우수, 나는 역학을 이해했습니다. 감사
Serg Burlaka
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.