๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿค์•ˆ๋“œ๋กœ์ด๋“œ ๊ฐœ๋ฐœ ๊ธฐ๋ก/โ˜€๏ธ ํ•˜๊ณ„ ์ธํ„ด ๊ฐœ๋ฐœ ํ”„๋กœ์ ํŠธ ๊ธฐ๋ก

Android : Handler ์ดํ•ดํ•˜๊ธฐ

by hyeonha 2024. 8. 29.

  • handler thread์™€ thread์˜ ์ฐจ์ด
  //๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ๋ฐ ์ฃผ๊ธฐ ์„ค์ • ์œ„ํ•œ ํ•ธ๋“ค๋Ÿฌ
    private val handlerThread = HandlerThread("SensorDataCollectionThread").apply { start() }
    private val handler = Handler(handlerThread.looper)

    private val collectDataRunnable = object : Runnable {
        override fun run() {
            if (!isCollectingData) { //1์ดˆ๋™์•ˆ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ์‹œ์ž‘
                isCollectingData = true
                startSensorDataCollection()
                handler.postDelayed({
                    //1์ดˆ ํ›„ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ์ค‘์ง€ ๋ฐ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ
                    stopSensorDataCollection()
                    processCollectedData()

                    isCollectingData = false
                    handler.postDelayed(this, selectedInterval.toLong())
                }, 1000)
            }
        }
    }

 

๊ณต์‹๋ฌธ์„œ

A Handler allows you to โ†’ ํ•ธ๋“ค๋Ÿฌ๋Š”

send and process Message and Runnable objects โ†’ ๋ฉ”์‹œ์ง€์™€ Runnable ๊ฐ์ฒด๋ฅผ ๋ณด๋‚ด๊ณ  ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

associated with a thread's MessageQueue.  โ†’ ์Šค๋ ˆ๋“œ์˜ MessageQueue์™€ ๊ด€๋ จ์žˆ๋Š”

ํ•ธ๋“ค๋Ÿฌ์˜ ์ฃผ์š” ๊ธฐ๋Šฅ

  1. ๋ฉ”์‹œ์ง€ ์ „์†ก
    1. Handler๋ฅผ ํ†ตํ•ด ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋กœ ๋ฉ”์‹œ์ง€๋‚˜ ์‹คํ–‰ํ•  ์ž‘์—…(Runnable)์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.
  2. ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ
    1. ๊ฐ ์Šค๋ ˆ๋“œ๋Š” MessageQueue๋ผ๋Š” ๋Œ€๊ธฐ์—ด์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
    2. Handler๋Š” ์ด ๋Œ€๊ธฐ์—ด์— ์žˆ๋Š” ๋ฉ”์‹œ์ง€๋‚˜ ์ž‘์—…์„ ์ˆœ์„œ๋Œ€๋กœ ๊บผ๋‚ด์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค.

Each Handler instance is associated with a single thread and that thread's message queue

๊ฐ ์Šค๋ ˆ๋“œ ๊ฐ์ฒด๋Š” ํ•˜๋‚˜์˜ ํŠน์ • ์Šค๋ ˆ๋“œ์™€ ๊ทธ ์Šค๋ ˆ๋“œ์˜ ๋ฉ”์‹œ์ง€ ํ์™€ ์—ฐ๊ฒฐ๋œ๋‹ค.

 

์Šค๋ ˆ๋“œ๊ฐ€ ์‚ฌ๋ฌด์‹ค

๋ฉ”์‹œ์ง€ ํ๋Š” ์‚ฌ๋ฌด์‹ค์˜ ํ•  ์ผ ๋ชฉ๋ก

ํ•ธ๋“ค๋Ÿฌ๋Š” ์ด ์‚ฌ๋ฌด์‹ค์˜ ๋น„์„œ

 

When you create a new Handler it is bound to a Looper. It will deliver messages and runnables to that Looper's message queue and execute them on that Looper's thread.

 

์ƒˆ๋กœ์šด ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ๊ทธ ํ•ธ๋“ค๋Ÿฌ๋Š” ํŠน์ • looper์™€ ์—ฐ๊ฒฐ๋œ๋‹ค.

์ด ํ•ธ๋“ค๋Ÿฌ๋Š” ๋ฉ”์‹œ์ง€์™€ ์‹คํ–‰๊ฐ€๋Šฅํ•œ ์ž‘์—…์ธ Runnable ๊ฐ์ฒด๋ฅผ ํ•ด๋‹น looper์˜ ๋ฉ”์‹œ์ง€ ํ์— ์ „๋‹ฌํ•˜๊ณ 

๊ทธ looper๊ฐ€ ์†ํ•œ ์Šค๋ ˆ๋“œ์—์„œ ์ด๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

 

looper : ํšŒ์ „๋ชฉ๋งˆ

handler : ํšŒ์ „๋ชฉ๋งˆ์— ๋ง(๋ฉ”์‹œ์ง€๋‚˜ ์ž‘์—…)์„ ์ถ”๊ฐ€ํ•˜๋Š” ์‚ฌ๋žŒ

๋ฉ”์‹œ์ง€ ํ : ํšŒ์ „ ๋ชฉ๋งˆ ์œ„์˜ ๋ง๋“ค

looper๊ฐ€ ์†ํ•œ ์Šค๋ ˆ๋“œ๋Š” ํšŒ์ „ ๋ชฉ๋งˆ๋ฅผ ๋Œ๋ฆฌ๋Š” ๋™๋ ฅ

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

  • ๋ฏธ๋ž˜์˜ ํŠน์ • ์‹œ์ ์— ๋ฉ”์‹œ์ง€์™€ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์ž‘์—…(Runnable)์„ ์˜ˆ์•ฝ
    • ์•Œ๋žŒ์‹œ๊ณ„๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•จ!!!
    • 3์ดˆ ํ›„์— ์ด ์ž‘์—…์„ ์‹คํ–‰ํ•ด๋ผ๊ณ  ํ•ธ๋“ค๋Ÿฌ์—๊ฒŒ ์ง€์‹œ ๊ฐ€๋Šฅ
    • ๋งค 5๋ถ„๋งˆ๋‹ค ์ด ์ž‘์—…์„ ๋ฐ˜๋ณตํ•ด๋ผ๊ณ  ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ์Œ
      • ์ผ์ • ์‹œ๊ฐ„ ํ›„ ํ™”๋ฉด ์—…๋Žƒ
      • ์ฃผ๊ธฐ์ ์ธ ๋ฐ์ดํ„ฐ ์ƒˆ๋กœ๊ณ ์นจ
      • ์ง€์—ฐ๋œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹คํ–‰
  • ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ๋Œ€๊ธฐ์—ด์— ๋„ฃ๊ธฐ
    • ๋‹ค๋ฅธ ๋ถ€์„œ์— ์—…๋ฌด๋ฅผ ์š”์ฒญํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šท!!
    • ๋„คํŠธ์›Œํฌ ์ž‘์—… ํ›„ UI ์—…๋ฐ์ดํŠธ

Handler์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์˜ˆ์•ฝํ•˜๋Š” ๋ฐฉ๋ฒ•

  • Post ๊ณ„์—ด ๋ฉ”์†Œ๋“œ : Runnable ๊ฐ์ฒด ์‚ฌ์šฉ
    • post(Runnable)
    • postAtTime(Runnable,long)
    • postDelayed(Runnable, Object, long)
handler.post {println("์ฆ‰์‹œ ์‹คํ–‰") }
handler.postDelayed( {println("3์ดˆ ํ›„ ์‹คํ–‰")}, 3000 )
  • sendMessage ๊ณ„์—ด ๋ฉ”์†Œ๋“œ : Message ๊ฐ์ฒด ์‚ฌ์šฉ
    • sendEmptyMessage(int)
    • sendMessage(Message)
    • sendMessageAtTime(Message,long)
  • Message๋Š” ๋ฐ์ดํ„ฐ ๋ฒˆ๋“ค์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์–ด ๋” ๋ณต์žกํ•œ ์ •๋ณด ์ „๋‹ฌ์— ์œ ์šฉํ•จ
val msg = Message.obtain()
msg.what = 1 // ๋ฉ”์‹œ์ง€ ์‹๋ณ„
msg.obj = "some data" // ์ „๋‹ฌํ•  ๋ฐ์ดํ„ฐ
handler.sendMessage(msg)

Runnable๊ณผ Message ์ฐจ์ด

  • Runnable : ์‹คํ–‰ํ•  ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์ •์˜
  • Message : ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ณ  Handler์˜ handlerMessage ๋ฉ”์†Œ๋“œ์—์„œ ์ฒ˜๋ฆฌ

์‚ฌ์šฉ ๋ฐฉ์‹

  • post : ๊ฐ„๋‹จํ•œ ์ž‘์—…์— ์ ํ•ฉ
  • sendMessage : ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ์ด ํ•„์š”ํ•  ๋•Œ ์‚ฌ์šฉ

๊ตฌํ˜„ ๋ฐฉ์‹

  • post : ๋ณ„๋„์˜ handler ์„œ๋ธŒ ํด๋ž˜์Šค๊ฐ€ ํ•„์š” ์—†๋‹ค
  • sendMessage : handler๋ฅผ ์ƒ์†๋ฐ›์•„ handlerMessage() ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„
// sendMessage ์‚ฌ์šฉ

class MyHandler : Handler() {
	override fun handleMessage(msg:Message) {
		when(msg.what) {
		 1 -> println("๋ฉ”์‹œ์ง€ 1 ๋ฐ›์Œ : ${msg.obj}")
		 2 ->  println("๋ฉ”์‹œ์ง€ 2 ๋ฐ›์Œ}")
		}
		}
	}
	
	val handler = MyHandler()
	handler.sendEmptyMessage(2)

Handler๋ฅผ ์‚ฌ์šฉํ•ด ์ž‘์—…์„ ์˜ˆ์•ฝํ•  ๋•Œ ์ฒ˜๋ฆฌ ์‹œ์  ์ •ํ•˜๊ธฐ

  1. ์ฆ‰์‹œ ์ฒ˜๋ฆฌ
    1. ๋ฉ”์‹œ์ง€ ํ๊ฐ€ ์ค€๋น„๋˜๋Š” ๋Œ€๋กœ ๋ฐ”๋กœ ์ฒ˜๋ฆฌ
    2. handler.post { } ๋˜๋Š” handler.sendMessage(msg)
  2. ์ง€์—ฐ ์ฒ˜๋ฆฌ
    1. ์ง€์ •๋œ ์‹œ๊ฐ„์ด ์ง€๋‚œ ํ›„์— ์ฒ˜๋ฆฌํ•œ๋‹ค.
    2. handler.postDelayed( { } , 1000 ) โ†’ 1์ดˆ ํ›„์— ์‹คํ–‰
    // 5์ดˆ ํ›„ ํƒ€์ž„ ์•„์›ƒ ์ฒ˜๋ฆฌ
    handler.postDelayed( {
    		if(!isTaskCompleted) {
    		println("์ž‘์—… ํƒ€์ž„์•„์›ƒ!")
    		}
    	},5000)
    
    // ์ฃผ๊ธฐ์ ์ธ ์ž‘์—…
    val tickRunnable = object : Runnable {
    	override fun run() {
    		println("ํ‹ฑ!")
    		handler.postDelayed(this,1000) // 1์ดˆ๋งˆ๋‹ค ๋ฐ˜๋ณต 
    		}
    	}
    handler.post(tickRunnable)
    
  3. ์ ˆ๋Œ€ ์‹œ๊ฐ„ ์ง€์ •
    1. ์ •ํ™•ํ•œ ์‹œ๊ฐ„์„ ์ง€์ •ํ•˜์—ฌ ๊ทธ ์‹œ์ ์— ์ฒ˜๋ฆฌ
    2. handler.postAtTime( { }, SystemClock.uptimeMillis() + 5000 ) // ํ˜„์žฌ๋กœ๋ถ€ํ„ฐ 5์ดˆ ํ›„ ์‹คํ–‰
    val futureTime = SystemClock.uptimeMillis() + 10000 // 10์ดˆ ํ›„์— ์‹œ๊ฐ„
    handler.postAtTime( {println("์ •ํ™•ํžˆ 10์ดˆ๊ฐ€ ์ง€๋‚ฌ์Šต๋‹ˆ๋‹ค") }, futureTime)
    

์•ˆ๋“œ๋กœ์ด๋“œ ์•ฑ์˜ ํ”„๋กœ์„ธ์Šค์™€ ์Šค๋ ˆ๋“œ ๊ตฌ์กฐ

  1. ๋ฉ”์ธ ์Šค๋ ˆ๋“œ(UI ์Šค๋ ˆ๋“œ)
    1. ์•ฑ์ด ์‹œ์ž‘๋  ๋•Œ ์ž๋™์œผ๋กœ ์ƒ์„ฑ
    2. ์ฃผ์š” ์—ญํ• 
      1. ๋ฉ”์‹œ์ง€ ํ ๊ด€๋ฆฌ
      2. ์ฃผ์š” ์•ฑ ๊ตฌ์„ฑ์š”์†Œ(์•กํ‹ฐ๋น„ํ‹ฐ, ๋ธŒ๋กœ๋“œ ์บ์ŠคํŠธ ๋ฆฌ์‹œ๋ฒ„) ๊ด€๋ฆฌ
      3. UI ๊ด€๋ จ ์ž‘์—… ์ฒ˜๋ฆฌ
  2. ์‚ฌ์šฉ์ž ์ •์˜ ์Šค๋ ˆ๋“œ
    1. ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ์ƒ์„ฑํ•˜๋Š” ์ถ”๊ฐ€ ์Šค๋ ˆ๋“œ
    2. ์ฃผ๋กœ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์„ ์ฒ˜๋ฆฌ
      1. ์˜ˆ ) ๋„คํŠธ์›Œํฌ ํ†ต์‹ , ํŒŒ์ผ ์ฒ˜๋ฆฌ

๋ฉ”์ธ ์Šค๋ ˆ๋“œ์™€ ์‚ฌ์šฉ์ž ์ •์˜ ์Šค๋ ˆ๋“œ ๊ฐ„์˜ ํ†ต์‹ 

  • Handler๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ •์˜ ์Šค๋ ˆ๋“œ์—์„œ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋กœ ๋ฉ”์‹œ์ง€๋‚˜ ์ž‘์—…์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ฐฉ๋ฒ• : post ๋˜๋Š” sendMessage() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉ
class MainActivity : AppCompatActivity() {
	private val handler = Handler(Looper.getMainLooper())
	
	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		setContentView(R.layout.activity_main)
		
		Thread {
			val result = performLongRunningTask()
			
			handler.post{
				updateUI(result)
			}
		}.start()
		}
		
	
 private fun performLongRunningTask(): String {
        // ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๋Š” ์ž‘์—… ์‹œ๋ฎฌ๋ ˆ์ด์…˜
        Thread.sleep(2000)
        return "์ž‘์—… ์™„๋ฃŒ!"
    }
  
 private fun updateUI(result: String) {
        // UI ์—…๋ฐ์ดํŠธ (๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋จ)
        findViewById<TextView>(R.id.resultTextView).text = result
   
  }
  •  

 

728x90