ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Android] Thread, Handler, Looper, Message Queue ๋‹ค๋ฃจ๊ธฐ
    Android 2021. 11. 11. 03:13
    ๋ฐ˜์‘ํ˜•

      Asynchronous Programming

     ์š”์ฆ˜ ๋Œ€๋ถ€๋ถ„์˜ ํ”„๋กœ๊ทธ๋žจ๋“ค์€ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰์ด ๋ฉ๋‹ˆ๋‹ค. ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์„ ์ด์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณ„๋„์˜ Thread๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋™์‹œ์ ์œผ๋กœ ์ž‘์—…์„ ์‹คํ–‰ํ•˜๊ฒŒ ํ•˜๋Š” ๋ฐฉ๋ฒ•๋ถ€ํ„ฐ AsyncTask, RxJava, RxKotlin, Coroutine ๋“ฑ ํŽธ๋ฆฌํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŽ์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ๋‚˜ํƒ€๋‚˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ ์ œ๊ณตํ•ด์ฃผ๋Š” Thread, Handler, Looper, Message Queue๋ฅผ ์ œ๋Œ€๋กœ ์•Œ๊ณ  ์žˆ์–ด์•ผ ๊ธฐ๋ณธ ์›๋ฆฌ๋ฅผ ๊นจ๋‹ซ๊ฒŒ ๋˜๊ณ  ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์˜ ํŽธ๋ฆฌํ•จ์„ ์•Œ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„ ๊ณต๋ถ€๋ฅผ ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. 

     

     

    Thread

     ์•ˆ๋“œ๋กœ์ด๋“œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ผ์™€ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰๋˜๊ณ  ์ž๋™์œผ๋กœ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ(Main Thread) ๊นŒ์ง€ ์ƒ์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. Main Thread์—์„œ๋Š” UI ๊ด€๋ จ๋œ ์ž‘์—…๋“ค์„ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, Main Thread ์ด์™ธ์˜ ์ผ๋ฐ˜ Thread์—์„œ๋Š” UI ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด EditText์˜ ๊ฐ’๋“ค์„ Thread1์—์„œ ๋ณ€๊ฒฝ ํ›„ ๋‚ด์šฉ์„ ์ฝ์„ ๋•Œ Thread2์—์„œ ๋‹ค๋ฅธ ๋‚ด์šฉ์œผ๋กœ ๋ณ€๊ฒฝ์„ ํ•˜๋ฉด ๊ธฐ๋Œ€ํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜ํƒ€๋‚  ์ˆ˜ ์—†๊ณ  ๊ฒฝ์Ÿ์ƒํƒœ(Race condition)๊ฐ€ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์•ˆ๋“œ๋กœ์ด๋“œ ์‹œ์Šคํ…œ์—์„œ๋Š” Main Thread์—์„œ๋งŒ UI๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค. 

     

    https://academy.realm.io/kr/posts/android-thread-looper-handler/

    Main Thread 

      ์ฃผ๋กœ UI ์ž‘์—…, UI ์Šค๋ ˆ๋“œ๋ผ๊ณ ๋„ ๋ช…์นญ, Main Thread์—์„œ UI ์ž‘์—…์ด ์•„๋‹Œ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์„ ํ•˜๊ฒŒ ๋˜๋ฉด ANR์ด ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ์Œ. ์•ˆ๋“œ๋กœ์ด๋“œ ์ปดํฌ๋„ŒํŠธ์˜ ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์†Œ๋“œ์™€ ๊ทธ ๋‚ด๋ถ€ ํ˜ธ์ถœ์€ ๋ชจ๋‘ Main Thread์—์„œ ์ฒ˜๋ฆฌ
    Activity์™ธ์—๋„ BroadcastReceiver, Service, Application ์ด UI์™€ ๊ด€๋ จ์ด ์—†๋”๋ผ๋„ Main Thread์—์„œ ์ž‘์—… ์ฒ˜๋ฆฌ

     

    ์ผ๋ฐ˜ Thread

      ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๊ธฐ ์œ„ํ•œ Thread ์ƒ์„ฑ, Network ์ž‘์—…, DB ์ฟผ๋ฆฌ ๋“ฑ ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…๋“ค์„ ์ฃผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜ Thread๋Š” ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ์ž‘์—…๋“ค์ด ๋งŽ์•„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ Thread๋ผ๊ณ ๋„ ๋ถ€๋ฅธ๋‹ค.

     

     

    โ€ป ANR (Application Not Response)

      ์•ˆ๋“œ๋กœ์ด๋“œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์„ ํ•˜๋ฉด์„œ ANR์€ ๋ชจ๋‘๊ฐ€ ํ•œ ๋ฒˆ์ฏค์€ ๊ฒฝํ—˜ํ•ด๋ดค์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ANR์€ ๋ง ๊ทธ๋ž˜๋„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋”์ด์ƒ ๋ฐ˜์‘ํ•˜์ง€ ์•Š๋Š” ์ƒํƒœ๋กœ Main Thread์—์„œ ๋„ˆ๋ฌด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ๊ฒฝ์šฐ ๋ฐœ์ƒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํฌ๊ทธ๋ผ์šด๋“œ ์ƒํƒœ์—์„œ ์ž‘์—… ์ง„ํ–‰ ์ค‘์— ANR์ด ๋ฐœ์ƒํ•˜๋ฉด ํŒ์—…์ด ๋‚˜ํƒ€๋‚˜๊ณ  ํ•ด๋‹น ํŒ์—…์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐ•์ œ์ข…๋ฃŒ ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•ˆ๋“œ๋กœ์ด๋“œ ์ปดํฌ๋„ŒํŠธ ์‹คํ–‰์€ Main Thread์—์„œ ํ•˜์—ฌ ์–ด๋””์„œ๋“  ANR์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋Œ€ํ‘œ์ ์œผ๋กœ ์ž์ฃผ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์‹œ์— ๋Œ€ํ•ด ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

     

    • Main Thread์—์„œ Network ์ž‘์—…๊ณผ ๊ฐ™์€ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ์†Œ์š”๋˜๋Š” ์ž‘์—… ์‹œ
    • BroadcastReceiver๊ฐ€ 5์ดˆ ์ด๋‚ด๋กœ ๋ฐ˜์‘ํ•˜์ง€ ์•Š์„ ์‹œ
    • Service์—์„œ๋„ ์˜ค๋žœ ์‹œ๊ฐ„ ๋™์•ˆ ๋ฆฌํ„ดํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ

     

     

     ์œ„์˜ ์„ค๋ช…๊ณผ ๊ฐ™์ด UI๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์ž‘์—…์€ Main Thread์—์„œ ์ฒ˜๋ฆฌํ•˜๊ณ  ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ์†Œ์š”๋˜๋Š” ์ž‘์—…์€ ์ผ๋ฐ˜ Thread๊ฐ€ ๋ณ„๋„๋กœ ์ƒ์„ฑํ•˜์—ฌ ์ฒ˜๋ฆฌํ•˜๋ฉด์„œ Thread ๊ฐ„ ํ†ต์‹ ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ๋„ ์ˆ™์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•œ Looper, Handler, Message Queue ๋“ฑ ๋‹ค์–‘ํ•œ ํด๋ž˜์Šค๊ฐ€ ์กด์žฌํ•˜๊ณ  ํ•ด๋‹น ํด๋ž˜์Šค์˜ ์—ญํ• ๊ณผ ํ†ต์‹  ๊ณผ์ •์„ ์ž˜ ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

     

    https://academy.realm.io/kr/posts/android-thread-looper-handler/

     

    Looper

      Looper ํด๋ž˜์Šค๋Š” Message Queue๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์—ญํ• ๋กœ Message๋‚˜ Runnable ๊ฐ์ฒด๋ฅผ ํ•˜๋‚˜์”ฉ ๊บผ๋‚ด์„œ Handler์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. Looperํด๋ž˜์Šค์™€ Message Queue๋กœ ์ธํ•ด UI์˜ ๊ฒฝ์Ÿ์ƒํƒœ(race condition)์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Looper.loop() ๋ฉ”์†Œ๋“œ ๋‚ด๋ถ€์—์„œ ๋ฌดํ•œ๋ฃจํ”„๋ฅผ ๋Œ๋ฉด์„œ Message Queue๋ฅผ ํ™•์ธํ•˜์—ฌ ํ•˜๋‚˜์”ฉ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

     

    public static void loop() {
            final Looper me = myLooper();
            if (me == null) {
                throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
            }
            final MessageQueue queue = me.mQueue;
    
            // Make sure the identity of this thread is that of the local process,
            // and keep track of what that identity token actually is.
            Binder.clearCallingIdentity();
            final long ident = Binder.clearCallingIdentity();
    
            // Allow overriding a threshold with a system prop. e.g.
            // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
            final int thresholdOverride =
                    SystemProperties.getInt("log.looper."
                            + Process.myUid() + "."
                            + Thread.currentThread().getName()
                            + ".slow", 0);
    
            boolean slowDeliveryDetected = false;
    
            for (;;) {
                Message msg = queue.next(); // might block
                if (msg == null) {
                    // No message indicates that the message queue is quitting.
                    return;
                }
                
                ...
                
                try {
                    msg.target.dispatchMessage(msg);
                    if (observer != null) {
                        observer.messageDispatched(token, msg);
                    }
                    dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
                }
            }
            ...
     }

      ๋ฉ”์†Œ๋“œ๋ฅผ ์ข€ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด๋ฉด ์ž์‹ ์˜ Looper๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ , Looper ํด๋ž˜์Šค์˜ ๋ฉค๋ฒ„๋ณ€์ˆ˜๋กœ MessageQueue๊ฐ€ ์žˆ์–ด์„œ ์ง์ ‘ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. MessageQueue์—์„œ ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณด๋ฉด์„œ msg๊ฐ€ null์ด ์•„๋‹ˆ๋ฉด dispatchMessage ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด Message๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ Looper๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ Message๊ฐ€ null์ด ๋ฉ๋‹ˆ๋‹ค.

     

     Main Thread์—๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์‹คํ–‰ ์‹œ์— Looper๋ฅผ ์ƒ์„ฑํ•˜์—ฌ Looper.getMainLooper() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์‰ฝ๊ฒŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ผ๋ฐ˜ Thread์—์„œ๋Š” Looper๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— run ๋ฉ”์†Œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜์—ฌ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋งŒ ์‹คํ–‰ํ•  ๋ฟ ๋ฉ”์„ธ์ง€๋ฅผ ๋ฐ›๊ฑฐ๋‚˜ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜ Thread์—์„œ๋„ ๋‹ค๋ฅธ Thread์—์„œ ๋ณด๋‚ด๋Š” ๋ฉ”์„ธ์ง€๋ฅผ ๋ฐ›๊ฑฐ๋‚˜ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ์ผ๋ จ์˜ ์ž‘์—…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

     

    • ์ผ๋ฐ˜ ์Šค๋ ˆ๋“œ์—์„œ๋„ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๊ธฐ ์œ„ํ•ด์„œ๋Š” Looper๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • Looper.prepare() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์Šค๋ ˆ๋“œ๋ณ„๋กœ Looper๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • ์ดํ›„ Looper.loop() ๋ฉ”์†Œ๋“œ์—์„œ MessageQueue๋ฅผ ํ•˜๋‚˜์”ฉ ํ™•์ธํ•˜์—ฌ Message๋ฅผ Handler์—๊ฒŒ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
    • Handler๋ฅผ ํ•ด๋‹น Message๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • Looper๋ฅผ ์ข…๋ฃŒํ•˜๊ธฐ ์œ„ํ•ด์„œ quit(), quitSafely() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. quit ํ•จ์ˆ˜๋Š” ์ฆ‰์‹œ ์ข…๋ฃŒํ•˜๊ณ , quitSafely๋Š” ์•ˆ์ „ํ•˜๊ฒŒ MessageQueue์— ์Œ“์ธ ๋ฉ”์„ธ์ง€๊นŒ์ง€ ์ฒ˜๋ฆฌํ•œ ํ›„ ์ข…๋ฃŒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

     

    ์ฐธ๊ณ 

    https://developer.android.com/reference/android/os/Looper#quitSafely() 

     

    Looper  |  Android Developers

     

    developer.android.com

     

    Message Queue

      MessageQueue๋Š” Looper ํด๋ž˜์Šค๋ฅผ ์„ค๋ช…ํ•˜๋ฉด์„œ ๋งŽ์ด ์„ค๋ช…ํ•˜์˜€์ง€๋งŒ ๋‹ค์‹œ ์„ค๋ช…ํ•˜์ž๋ฉด Message๋ฅผ ๋‹ด๋Š” Queue ํ˜•ํƒœ์˜ ์ž๋ฃŒ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. MessageQueue๋Š” Message๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ Queue์—์„œ ์‚ญ์ œํ•˜๊ณ , Message๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ๋Š” Queue์— ์ถ”๊ฐ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ถ”๊ฐ€, ์‚ญ์ œ๊ฐ€ ์šฉ์ดํ•œ ๊ตฌ์กฐ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. MessageQueue๋Š” LinkedBlockingQueue๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์œผ๋ฉฐ ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ์™€ ๊ฐ™์€ ๊ตฌ์กฐ๋กœ ๋‹ค์Œ ๋…ธ๋“œ์— ๋Œ€ํ•œ ๋งํฌ๋ฅผ ๊ฐ€์ง€๋Š” ๋ฐฉ์‹์œผ๋กœ ํ•˜์—ฌ Message ์ถ”๊ฐ€, ์‚ญ์ œ๋ฅผ ๋น ๋ฅด๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. MessageQueue์—๋Š” ํ•ด๋‹น Message๊ฐ€ ์‹คํ–‰๋˜๋Š” ์ˆœ์„œ๋Œ€๋กœ ์ถ”๊ฐ€๊ฐ€ ๋˜๋ฉฐ, ์ค‘๊ฐ„์— ๋จผ์ € ์ฒ˜๋ฆฌ๊ฐ€ ๋˜์–ด์•ผ ํ•˜๋Š” Message๊ฐ€ ๋“ค์–ด์˜ค๋ฉด ์ค‘๊ฐ„์— ์‚ฝ์ž…์ด ๋  ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    ์ฐธ๊ณ 

    https://developer.android.com/reference/android/os/MessageQueue

     

    MessageQueue  |  Android Developers

     

    developer.android.com

     

    Handler

       Handler๋Š” Looper๋กœ ๋ถ€ํ„ฐ ์ฒ˜๋ฆฌ๋˜์–ด์•ผ ํ•  Message๋“ค์„ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ์—ญํ• ๊ณผ, ๋‹ค์‹œ Message Queue์— Message๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, Handler๋ฅผ ํ†ตํ•ด ๋‹ค๋ฅธ Thread์—์„œ ์š”์ฒญํ•˜๋Š” ๋ฉ”์„ธ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ๋‹ค์‹œ ํ•ด๋‹น Thread์— ๋ฉ”์„ธ์ง€๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— Thread๊ฐ„์˜ ํ†ต์‹ ์„ ๋‹ด๋‹นํ•œ๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    https://developer.android.com/reference/android/os/Handler

     

    ์›๋ž˜๋Š” Handler์˜ ๊ธฐ๋ณธ ์ƒ์„ฑ์ž๋Š” 4๊ฐœ๋กœ ์ •์˜๋˜์–ด ์žˆ์—ˆ์ง€๋งŒ, ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฒ„๊ทธ๋“ค๋กœ ์ธํ•˜์—ฌ ์•„๋ž˜ 2๊ฐœ์˜ ์ƒ์„ฑ์ž ์ฆ‰ Looper๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๊ณ  Looper์™€ Callback์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๋Š” ์ƒ์„ฑ์ž๋งŒ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

     

    class LooperThread extends Thread{
        public Handler mHandler;
    
        @Override
        public void run() {
            Looper.prepare();
            mHandler = new Handler(Looper.myLooper()){
                @Override
                public void handleMessage(@NonNull Message msg) {
                    // ๋ฉ”์„ธ์ง€ ์ฒ˜๋ฆฌ
                    super.handleMessage(msg);
                }
            };
            Looper.loop();
        }
    }

      ๋‹ค์Œ ์ฝ”๋“œ์—์„œ Looper.prepare์™€ Looper.loop์ฝ”๋“œ๊ฐ€ ์—†์œผ๋ฉฐ NullPointerException(NPE)๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. Handler์˜ ์ƒ์„ฑ์ž์—๋Š” Looper๊ฐ€ ๋“ค์–ด๊ฐ€์•ผํ•˜๊ณ  myLooper๋ฅผ ํ†ตํ•ด์„œ TLS(Thread Local Storage)์— ์ €์žฅ๋œ Looper๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ prepare ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์œผ๋ฉด MessageQueue๊ฐ€ ์ƒ์„ฑ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— null์ด ๋˜์–ด ํ•ด๋‹น ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ผ๋ฐ˜ ์Šค๋ ˆ๋“œ์—์„œ Handler๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Looper๋ฅผ ๋ฌด์กฐ๊ฑด ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

     

     

    Handler์˜ ์ฃผ์š” ์šฉ๋„

    1. ์ผ๋ฐ˜ ์Šค๋ ˆ๋“œ์—์„œ UI ์—…๋ฐ์ดํŠธ

     ์ผ๋ฐ˜ ์Šค๋ ˆ๋“œ์—์„œ ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์ด๋‚˜ DB ์ž‘์—… ์‹œ UI ์—…๋ฐ์ดํŠธ๊ฐ€ ํ•„์š”ํ•  ๊ฒฝ์šฐ Main Thread์˜ Handler๋ฅผ ํ†ตํ•ด ์—…๋ฐ์ดํŠธ ์ž‘์—…์„ Runnable์ด๋‚˜ Message๋ฅผ ํ†ตํ•ด ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Œ

     

    2. ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ๋‹ค์Œ ์ž‘์—… ์˜ˆ์•ฝ

      ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ UI ์ž‘์—…์„ ๋ฐ”๋กœ ํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋•Œ API ์ค‘ Delayed๊ฐ€ ๋ถ™์€ ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ํŠน์ • ์‹œ๊ฐ„ ์ดํ›„์— ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก Handler๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ

     

    3. ๋ฐ˜๋ณต ๊ฐฑ์‹ 

      ๋ฐ˜๋ณตํ•ด์„œ UI๋ฅผ ๊ฐฑ์‹ ํ•  ๋•Œ Handler์— Runnable ๊ฐ์ฒด๋ฅผ ๋Œ€์ž…ํ•˜๊ณ  Runnable ๊ฐ์ฒด์—์„œ๋Š” ํ•ด๋‹น Handler๋ฅผ ๊ฐ€์ง€๊ณ  ๋‹ค์‹œ Runnable์„ ํ˜ธ์ถœํ•˜๋Š” ์žฌ๊ท€์ ์ธ ๋ฐฉ์‹์œผ๋กœ ์ฝ”๋“œ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ฒ˜์Œ Handler ํ˜ธ์ถœ์€ post ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ดํ›„ Runnable ๊ฐ์ฒด๋Š” postDelayed๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋ฐ˜๋ณต์ ์œผ๋กœ ์ฃผ๊ธฐ๋งˆ๋‹ค Runnable ๊ฐ์ฒด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

     

    4. ์‹œ๊ฐ„ ์ œํ•œ

      ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ ์‹œ๊ฐ„ ์ œํ•œํ•  ๋•Œ๋„ Handler๋ฅผ ์ฃผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋’ค๋กœ ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์„ ๋”๋ธ” ํด๋ฆญ ์‹œ ํŠน์ • ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๊ณ  ํ–ˆ์„ ๋•Œ ๋”๋ธ” ํด๋ฆญ์— ๋Œ€ํ•œ ์‹œ๊ฐ„์„ ์ œํ•œ์„ ๋‘์–ด์„œ ์‹œ๊ฐ„ ์ œํ•œ์•ˆ์— ํด๋ฆญ์ด๋ฒคํŠธ๊ฐ€ ํ•œ ๋ฒˆ ๋” ์ž…๋ ฅ์ด ๋˜๋ฉด ํŠน์ • ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

     ex) 2์ดˆ ์•ˆ์— ๋’ค๋กœ๊ฐ€๊ธฐ ๋”๋ธ” ํด๋ฆญ ์‹œ ์•กํ‹ฐ๋น„ํ‹ฐ ์ข…๋ฃŒ, ์ฒ˜์Œ ํด๋ฆญ ์‹œ  finish ๋ณ€์ˆ˜ true ๋ณ€๊ฒฝ, ํ•œ ๋ฒˆ ๋” ํด๋ฆญ ์‹œ finish๊ฐ€ true๋ฉด ์ข…๋ฃŒ
    ํ•˜์ง€๋งŒ 2์ดˆ ์•ˆ์— ๋”๋ธ” ํด๋ฆญ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์œผ๋ฉด Handler์˜ postDelayed๋กœ ์„ค์ •๋œ ์ด๋ฒคํŠธ๊ฐ€ finish๋ฅผ false๋กœ ๋ณ€๊ฒฝ

     

     

    ์ฐธ๊ณ 

     

    ์•ˆ๋“œ๋กœ์ด๋“œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž˜ ๋‹ค๋ฃจ๊ธฐ Thread, Looper, Handler

    ์•ˆ๋“œ๋กœ์ด๋“œ UI๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ ๋ชจ๋ธ๋กœ ์ž‘๋™ํ•˜๋ฏ€๋กœ, ์ด ์˜ํ–ฅ์„ ๊ณ ๋ คํ•ด ๊ฐœ๋ฐœํ•˜์ง€ ์•Š์œผ๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ฑ๋Šฅ์ด ์ €ํ•˜๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ๊ธด ์ž‘์—…์„ ํ•˜๋Š” ๊ฒƒ์„ ํ”ผํ•˜

    academy.realm.io

     

    ๋ฐ˜์‘ํ˜•

    'Android' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

    [Android] Context, ContextWrapper, ContextImpl ์ดํ•ด  (0) 2021.11.21
    [Android] Preference, Shared Preference?  (0) 2021.11.19
    [Android] Activity๋ž€? Activity LifeCycle ์™„๋ฒฝ ์ดํ•ด  (0) 2021.11.03
    [Android] Drawble layer-list  (0) 2021.08.15
    [Android] Robelctric Test๋ž€  (0) 2021.02.17
Designed by Tistory.