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

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