Android์ Thread, Handler, Looper ์ ๋ํ์ฌ
์์ฑ์ : ๋ฐํ์
Present Time : 2018โ06-03-SUN
Last Updated : 2018-
ํ๋ก์ธ์ค์์ ์ ์ผ ์ฒ์ ์คํ๋๋ ์ค๋ ๋๋ฅผ ๋งํ๋ค. ๋ฉ์ธ ์ค๋ ๋๋ ์์ฉํ๋ก๊ทธ๋จ์ ์์๊ณผ ํจ๊ป ์์๋๊ณ ํด๋น ์์ฉํ๋ก๊ทธ๋จ์ ํ๋ก์ธ์ค์ ๊ฐ์ ์๋ช ์ ๊ฐ์ง๋ค. ๋ฉ์ธ ์ค๋ ๋๋ UI๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ ์ ์ผํ ์ค๋ ๋์ด๊ธฐ ๋๋ฌธ์ UI์ค๋ ๋๋ผ๊ณ ๋ถ๋ฅด๊ธฐ๋ ํ๋ค. UI์ค๋ ๋๋ ์๋๋ก์ด๋ ๊ตฌ์ฑ์์๋ฅผ ์คํํ๊ณ ํ๋ฉด UI์์๋ฅผ ๋ณ๊ฒฝํ๋ ๋ฐ ์ฌ์ฉํ๋ ์์ฉํ๋ก๊ทธ๋จ์ ๋ฉ์ธ ์ค๋ ๋์ด๋ค.
๋ฉ์ธ ์ค๋ ๋์์ ํ์๋์ด ์คํ๋๋ ์ค๋ ๋
๋ค์ํ ์ข ๋ฅ์ ์ค๋ ๋๋ก ๋์์ ํธ์ถํ ์ ์๋ ๋ฉ์๋๋ฅผ ๋จ์ผ ์ค๋ ๋ ๋ชจ๋ธ์ด๋ผ ํ๋ค. ์์คํ ๋ด์์ ํด๋น ์์ ๋๋ ํด๋น ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ์์ ์๋ ๋ฐ๋์ ํ๋์ ์ค๋ ๋๋ง ์คํ๋์ด์ผ ํ๋ค. ์ค๋ ๋๋ก๋ถํฐ ์์ ํ์ง ๋ชปํ (Thread-Unsafe) ๋ฉ์๋ ๋ผ๊ณ ๋ถ๋ฅด๊ธฐ๋ ํ๋ค.
๋ทฐ๋ ๋ทฐ๊ทธ๋ฃน์์ ์ ๊ณตํ๋ ๋ฉ์๋ ๋ ๋จ์ผ ์ค๋ ๋ ๋ชจ๋ธ์ด๋ค.
ํ๋์ ์์์ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ์ฌ์ฉํ ๋ ํ ์์ ์์ ํ๋์ ์ค๋ ๋๋ง ์ ๊ทผ์ ํ์ฉํ๋ ๊ธฐ๋ฅ์ด๋ค.
Ex) ํ๋ฆฐํฐ : ๋ฌธ์๋ฅผ ์ถ๋ ฅํ๊ณ ์๋ ๋์ ๋ค๋ฅธ ๋ฌธ์๋ฅผ ๋์์ ํ๋ฆฐํฐ๋ก ์ถ๋ ฅํ ์ ์๋ค.
์ค๋ ๋๋ ์ฝ๊ฒ ๋งํด ์ฌ๋ฌ์์ ์ ๊ฐ์ด ํ๊ธฐ ์ํ ๊ธฐ๋ฅ์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค. ์๋ฅผ ๋ค์ด ์์ ์ ๋ค์ผ๋ฉด์ SNS๋ฅผ ํ ์ ์๋ ๊ฒ์ฒ๋ผ ๋ง์ด๋ค.
์ดํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅํฅ์์ ์ํด ๋ฉํฐ ์ค๋ ๋๋ฅผ ๋ง์ด ์ฌ์ฉํ์ง๋ง, UI๋ฅผ ์ ๋ฐ์ดํธ ํ ๋๋ ๋จ์ผ ์ค๋ ๋ ๋ชจ๋ธ์ด ์ ์ฉ๋๋ค. ๋ฉํฐ ์ค๋ ๋๋ก UI๋ฅผ ์ ๋ฐ์ดํธ ํ๋ฉด ๋์ผํ UI์์์ ์ฌ์ฉํ ๋ *๊ต์ฐฉ ์ํ, *๊ฒฝํฉ ์ํ ๋ฑ ์ฌ๋ฌ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค. ๋ฐ๋ผ์ UI์ ๋ฐ์ดํธ๋ ๋ฉ์ธ์ค๋ ๋์์๋ง ํ์ฉํ๋ค.
๋ฉ์ธ์ค๋ ๋ ๋ง์ผ๋ก ๊ตฌํํ๊ฒ ๋๋ค๋ฉด, ์ฌ์ฉ์๋ ํด๋น ์์ ์ด ๋๋ ๋๊น์ง ๋ฉ์ถฐ์๋ ํ๋ฉด์ ๋ณด๊ณ ๋ง ์์ด์ผํ๋ค. ์ค๋ ์๊ฐ๋์ UI๊ด๋ จ ์์ ์ด ์ฒ๋ฆฌ๋์ง ๋ชปํ๋ฉด ๊ฒฐ๊ตญ *ANR ์๋ฌ๊ฐ ๋ฐ์ํ๋ค. ๊ทธ๋ฌ๋ฉด ์ดํ๋ฆฌ์ผ์ด์ ์ ์ ์ง๋๋ค.
์๋๋ก์ด๋ 3.0 ๋ฒ์ ๋ถํฐ ํต์ ํด๋์ค ๋ด ์ ์ก์ด๋ ์์ ๊ณผ ๊ด๋ จ๋ ๋ฉ์๋๋ ๋ฉ์ธ ์ค๋ ๋์์ ์ฌ์ฉํ์ง ๋ชปํ๋๋ก ์๋์ ์ผ๋ก ๋ง์๋ฒ๋ ธ๋ค. EX) ๋ฉ์ธ ์ค๋ ๋์์ ์์ผํด๋์ค์ conntect() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด 'NetworkOnMainThreadException' ์ด ๋ฐ์ํ๋ค.
์์๊ฐ์ ๋คํธ์ํฌ ํต์ ๊ธฐ๋ฅ์ด๋ ๋ฐ์ดํฐ ๊ฒ์, ๋น๋ฒํ๊ฒ ์ฌ์ฉํ๋ ํ์ผ์ ๋ก๋๊ณผ ๊ฐ์ด ์๊ฐ์ด ๊ฑธ๋ฆฌ๋ ์์ ๋ค์ ์ฌ์ฉ์๊ฐ ๊ธฐ๋ค๋ฆฌ์ง ์๋๋ก ํ๊ธฐ ์ํ์ฌ ์ฌ๋ถ์ ์ค๋ ๋๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค. (๋ฉํฐ์ค๋ ๋)
์๋๋ก์ด๋ ์ฑ์ ์ ๋๋ก ๊ฐ๋ฐํ๊ธฐ ์ํด์๋ ๋ฉํฐ ์ค๋ ๋๋ฅผ ์ด์ฉํ๋ ๊ฒ์ ํ์์ ์ด๋ผ ํ ์ ์๋ค.
์ค๋ ๋๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ 2๊ฐ์ง๊ฐ ์๋ค. ํ๋๋ Thread๋ฅผ ์ด์ฉํ๋ ๊ฒ์ด๊ณ , ๋๋จธ์ง ํ๋๋ Runnable์ ์ด์ฉํ๋ ๊ฒ์ด๋ค.
public class TaeiimThread extends Thread {
@Override
public void run() {
super.run();
// Do something..
}
}
// ์ค๋ ๋ ์คํ
TaeiimThread thread = new TaeiimThread();
thread.start();
Runnable ์ธํฐํ์ด์ค๋ฅผ ์์๋ฐ์ ํ, run() ๋ฉ์๋์ ์ํ๋ ์์ ์ ํ๋๋ก ๊ตฌํํ๋ฉด ๋๋ค.
์์ฑ๋ ํด๋์ค๋ฅผ ์์ฑํ ํ, Thread ํด๋์ค์ ์์ฑ์์ ์ธ์๋ก ์ ๋ฌํ๋ค.
public class TaeiimRunnable implements Runnable {
@Override
public void run() {
// Do something,,
}
}
// ์ฌ์ฉํ๊ธฐ
TaeiimRunnable myRunnable = new TaeiimRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
Thread์ Runnable ์ ๋ช๊ฐ์ง ์ฐจ์ด์ ์ด ์๋ค.
-
Thread๋ ์์(Extends)์ ๋ฐ๋ ๊ฒ์ด๋ฉฐ Runnable์ ์ธํฐํ์ด์ค๋ก์ ๊ตฌํํ๋ ๊ฒ์ด ํฐ ์ฐจ์ด์ ์ด๋ค.
์๋ฐ๋ ๋ค์ค ์์์ด ๋ถ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ Thread๋ฅผ ์์๋ฐ๊ฒ ๋์ ํด๋์ค๋ ๋ค๋ฅธ ํด๋์ค๋ฅผ ์์ ๋ฐ์ ์๊ฐ ์์ง๋ง Runnable์ ์ธํฐํ์ด์ค์ด๊ธฐ ๋๋ฌธ์ implements๋ง ํ๋ฉด ๋๊ณ ๋ค๋ฅธ ํ์ํ ํด๋์ค๋ฅผ ์์ ๋ฐ์ ์ ์๋ค.
-
Thread๋ ์ฌ์ฌ์ฉ ๋ถ๊ฐ๋ฅ, Runnable ๊ฐ๋ฅ
์ค๋ ๋๋ ์ผํ์ฉ์ด๋ค. ๋ฐ๋ผ์ ํ ๋ฒ ์ฌ์ฉํ ์ค๋ ๋๋ ์ฌ์ฌ์ฉํ ์ ์๋ค. ์ฌ์ฌ์ฉ์ 'IllegalThreadStateException' ์ด ๋ฐ์ํ๋ค. ์ฆ, ํ๋์ ์ค๋ ๋์ ๋ํด start()๊ฐ ํ ๋ฒ๋ง ํธ์ถ๋ ์ ์๋ค. ํ์ง๋ง, Runnable๋ก ๊ตฌํํ ๊ฒฝ์ฐ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
์ฉ์ด์ ๋ฆฌ
*๊ต์ฐฉ์ํ(dead lock): ๋ ๊ฐ ์ด์์ ์์ ์ด ์๋ก ์๋๋ฐฉ์ ์์ ์ด ๋๋๊ธฐ ๋ง์ ๊ธฐ๋ค๋ฆฌ๊ณ ์๊ธฐ ๋๋ฌธ์ ๊ฒฐ๊ณผ์ ์ผ๋ก ์๋ฌด๊ฒ๋ ์๋ฃ๋์ง ๋ชปํ๋ ์ํ
*๊ฒฝํฉ์ํ(race condition) : ๋ ๊ฐ ์ด์์ ํ๋ก์ธ์ค๊ฐ ๊ณตํต ์์์ ๋ณํ์ ์ผ๋ก ์ฝ๊ฑฐ๋ ์ธ ๋, ๊ณต์ฉ๋ฐ์ดํฐ์ ๋ํ ์ ๊ทผ์ด ์ด๋ค ์์์ ๋ฐ๋ผ ์ด๋ฃจ์ด์ก๋์ง์ ๋ฐ๋ผ ๊ทธ ์คํ ๊ฒฐ๊ณผ๊ฐ ๋ฌ๋ผ์ง๋ ์ํฉ
*ANR : ์๋๋ก์ด๋์์๋ ์ด๋ค ์์ ์ ์์ฒญํ๊ณ 5์ด๊ฐ์ ์๋ต์ด ์์ ๋ ๊ฐ์ ์ข ๋ฃ ์ฌ๋ถ๋ฅผ ๋ฌป๋ ๋ค์ด์ผ๋ก๊ทธ๋ฅผ ๋ฐ์์ํจ๋ค. ์ด ๋ค์ด์ผ๋ก๊ทธ๋ฅผ ANR(Application not responding) ๋ฉ์์ง ๋ผ๊ณ ํ๋ค.
Handler๋ Looper๋ก๋ถํฐ ๋ฐ์ Message๋ฅผ ์คํ, ์ฒ๋ฆฌํ๊ฑฐ๋ ๋ค๋ฅธ ์ค๋ ๋๋ก๋ถํฐ ๋ฉ์์ง๋ฅผ ๋ฐ์์ Message Queue์ ๋ฃ๋ ์ญํ ์ ํ๋ ์ค๋ ๋ ๊ฐ์ ํต์ ์ฅ์น์ด๋ค.
ํธ๋ค๋ฌ๋ ๋ ์ข ๋ฅ์ ๊ฐ์ฒด๋ฅผ **๋ฉ์์ง ํ(Message Queue)**๋ฅผ ํตํด ํน์ ์ค๋ ๋๋ก ์ ๋ฌํ๋ค.
- ๋ฌธ์์ ํ๋๋ก ๊ตฌ์ฑ๋ ๋ฉ์์ง ๊ฐ์ฒด
- Runnable ๊ฐ์ฒด
๋ฉ์์งํ๋ ํ๋์ ํ๋ก์ธ์ค ๋ด ์๋ธ์ค๋ ๋๊ฐ ๋ค๋ฅธ ํ๋ก์ธ์ค ๋ด ์กด์ฌํ๋ ์ค๋ ๋์ ๋ฉ์์ง๋ฅผ ์ ๋ฌํ๋ ๊ธฐ๋ฅ์ ํ๋ค.
ํธ๋ค๋ฌ๋ ๋ฐ๋์ ๋ฉ์์งํ๊ฐ ์ ๊ณต๋๋ ์ค๋ ๋์์ ์์ฑํด์ผํ๋ค. ๋ฉ์ธ ์ค๋ ๋๋ ๊ธฐ๋ณธ์ผ๋ก ๋ฉ์์งํ๋ฅผ ์ ๊ณตํ๋ค.
ํธ๋ค๋ฌ๋ ์ผ๋ฐ์ ์ผ๋ก UI๊ฐฑ์ ์ ์ํด ์ฌ์ฉ๋๋ค.
-
๋ฉ์๋๊ฐ ๋จ์ผ ์ค๋ ๋ ๋ชจ๋ธ์ผ ๋ , Thread-Safe๋ก ๋ง๋ค๊ธฐ ์ํด
์๋์ ์ฝ๋๋ฅผ ์คํ์ํค๋ฉด 'CalledFromWrongThreadException' ์ด๋ผ๋ ์์ธ๊ฐ ๋ฐ์ํ๋ค. ์ด๊ฒ์ ๋ทฐ ํด๋์ค์์ ์ ๊ณตํ๋ ๋ฉ์๋(์ฌ๊ธฐ์๋ setText()) ๋ฅผ ๋ฉ์ธ์ค๋ ๋(UI ์ค๋ ๋) ๊ฐ ์๋ ์๋ธ ์ค๋ ๋์์ ์คํ ์์ผฐ๊ธฐ ๋๋ฌธ์ด๋ค.
0-2์์ ์ธ๊ธํ๋ฏ์ด, ๋ทฐ๋ ๋ทฐ๊ทธ๋ฃน์์ ์ ๊ณตํ๋ ๋ฉ์๋๋ ๋จ์ผ ์ค๋ ๋ ๋ชจ๋ธ(Thread-Unsafe)์ด๊ธฐ ๋๋ฌธ์ ๋ฉ์ธ ์ค๋ ๋์์ ํธ์ถํด์ผ ํ๋ค.
public class TaeiimThread extends Thread { @Override public void run() { super.run(); textView.setText("๋ฐํ์ ์งฑ"); // Error!! } }
์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด **์๋ฐ๋ ๋๊ธฐํ(Synchronized)**๋ผ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ง๋ง, ์๋๋ก์ด๋๋ ํธ๋ค๋ฌ๋ฅผ ์ ๊ณตํ๋ค.
์ค๋ ๋์์ ๋คํธ์ํฌ ๋ฑ์ ์์ ๋ค์ ํ๋ ๋์ค์ UI๋ฅผ ์ ๋ฐ์ดํธ ํ ๋ ํธ๋ค๋ฌ๋ฅผ ์ฌ์ฉํ๋ค.
-
ํ๋์ ํ๋ก์ธ์ค์์ ๋ค๋ฅธ ํ๋ก์ธ์ค์ ํธ๋ค๋ฌ์ ๋ฉ์์ง๋ฅผ ์ ์กํ์ฌ ์์ ์ ์์ฒญํ ๋
๋ ๋ฆฝ์ ์ผ๋ก ์คํ๋๋ ์ค๋ ๋ ์ฌ์ด์ ์ ๋ณด๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ์๋จ์ผ๋ก ๋ฉ์์งํ์ ํธ๋ค๋ฌ๋ฅผ ์ฑํํ๋ค. ๋ง์ฝ ์ผ๋ฐ ์ค๋ ๋์ฌ์ด์์ ํ์ํ ์ ๋ณด๋ฅผ ์ฃผ๊ณ ๋ฐ์ผ๋ ค๋ฉด ๋ฃจํผ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
๋ค์์ Handler๋ฅผ ์ด์ฉํด 1์ด์ฉ ์ฆ๊ฐํ๋ ํ์ด๋จธ๋ฅผ ๋ง๋ ์์ ์ด๋ค.
package com.example.parktaeim.threadex;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity{
TextView timeTv;
Button startBtn;
Runnable timeRunnable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
timeTv = (TextView) findViewById(R.id.timeTv);
startBtn = (Button) findViewById(R.id.startBtn);
startBtn.setOnClickListener(v->{
// Runnable ๊ฐ์ฒด๋ฅผ ๋งค๊ฐ๋ณ์๋ก Thread ์์ฑ
Thread timeThread = new Thread(timeRunnable);
timeThread.start(); // Thread Start
});
timeRunnable = new Runnable() {
@Override
public void run() {
int time = 0;
while(true){
Message msg = new Message();
msg.what = 0;
msg.arg1 = time;
handler.sendMessage(msg); // Handler์ Message ๋ณด๋
try{
Thread.sleep(1000);
time++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what == 0){
timeTv.setText(String.valueOf(msg.arg1));
}
}
};
}
Looper๋ ๋ฌดํํ ๋ฃจํ๋ฅผ ๋๋ฉฐ ์์ ํ ์ํ ์ค๋ ๋์ Message Queue์์ Message๋ Runnable ๊ฐ์ฒด๋ฅผ ์ฐจ๋ก๋ก ๊บผ๋ด Handler๊ฐ ์ฒ๋ฆฌํ๋๋ก ์ ๋ฌํ๋ค.
๋ฉ์ธ ์ค๋ ๋์๋ Looper๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ์์ฑ๋์ด ์์ง๋ง, ์๋ก ์์ฑํ ์ค๋ ๋๋ Looper๋ฅผ ๊ฐ์ง๊ณ ์์ง ์๊ธฐ ๋๋ฌธ์ ๋ฉ์์ง๋ฅผ ๋ฐ์ ์ ์๋ค. ์ฌ์ฉํ ์ ์๋ ๋ฉ์์ง ํ๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์๋ธ ์ค๋ ๋์์ ๋ฉ์์ง๋ฅผ ์ ๋ฌ๋ฐ๊ธฐ ์ํด์๋ Looper๋ฅผ ์์ฑํด์ฃผ์ด์ผ ํ๋ค.
-
๋ฃจํผ ํด๋์ค๋ ์์ฑ์๋ฅผ ์ฌ์ฉํ์ฌ ์ธ์คํด์ค๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํ๋ ๊ฒ์ด ์๋๋ผ ์ ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค.
public final class Looper { ... ... //Looper ํด๋์ค์ prepare(), loop() ๋ฑ์ ๋ฉ์๋๋ค์ ์ ์ ๋ฉ์๋๋ก ๋์ด์๋ค. public static void prepare() { prepare(true); } public static void loop() { ...... } ... ... }
// ๊ทธ๋์ ๊ฐ์ฒด๋ฅผ ์์ฑํ์ง ์์๋ ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋ค. Looper.prepare(); Looper.loop();
-
๋ฃจํผ๋ ํธ๋ค๋ฌ๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ๋ฉ์์งํ์ ์ฐ๊ฒฐ์์ผ ์ค๋ค.
Looper.prepare(); ํ์ ๋ ์คํ๋๋ ์์
public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
// prepare(boolean quitAllowed) ๋ฉ์๋์์ new Looper() private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); // MessageQueue ์ฌ๊ธฐ์ ์์ฑ mThread = Thread.currentThread(); }
๋ฃจํผ๋ ํด๋์ค๋ฅผ ์ธ์คํด์คํํ๊ณ ๊ฐ์ฒด ๋ด ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ์ผ๋ฐ์ ์ธ ์๋ฐ ํ๋ก๊ทธ๋จ๊ณผ ๋ค๋ฅด๊ฒ
๋ฃจํผ ์ด๊ธฐํ -> ํธ๋ค๋ฌ ์์ฑ -> ๋ฃจํผ ์คํ ์ด๋ผ๋ 3๋จ๊ณ๋ก ์์ ์ ์ํํ๋ค.
public class LooperEx extends Thread {
public Handler handler;
@Override
public void run() {
Looper.prepare(); // Looper ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ๋ฉ์์งํ๋ฅผ ์ด๊ธฐํ
handler = new Handler(){ // ํธ๋ค๋ฌ ๊ฐ์ฒด ์์ฑ
@Override
public void handleMessage(Message msg) {
// ๋ฉ์์ง ์ฒ๋ฆฌ
}
};
// ์ค๋ ๋ ๋ด ํธ๋ค๋ฌ์ ๋ฉ์์ง๋ฅผ ์ ๋ฌ. ์ค๋ ๋๊ฐ ์ข
๋ฃ๋์ง ์๋๋ก ๋ด๋ถ์ ์ผ๋ก ๋ฉ์์ง๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๊ธฐ๋ฅ.
Looper.loop();
}
}
๋ฉ์ธ ์ค๋ ๋์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก Looper๊ฐ ์ ๊ณต๋์ง๋ง ์๋ธ์ค๋ ๋์์๋ Looper๋ฅผ ๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ์ง์ง ์์ ์ง์ ์์ฑํด์ฃผ์ด์ผ ํ๋ ๋ถํธํจ์ด ์๋ค. ์ด์ ๊ฐ์ ๋ถํธํจ์ ๊ฐ์ ํ๊ธฐ ์ํด ์์ฑํ ๋ Looper๋ฅผ ์๋์ผ๋ก ๋ณด์ ํ ํด๋์ค๋ฅผ ์ ๊ณตํ๋๋ฐ ๊ทธ๊ฒ์ด ๋ฐ๋ก HandlerThread์ด๋ค.
์๋๋ก์ด๋๋ ์ค๋ ๋๋ก๋ถํฐ ์์ ํ์ง ๋ชปํ ๋ฉ์๋๋ฅผ ํธ์ถํ ๋๋ ํธ๋ค๋ฌ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ ์ด์ธ์๋ ๋ค์๊ณผ ๊ฐ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
- Activity.runOnUiThread(Runnable)
- View.post(Runnable) , View.postDelayed(Runnable, long)
์์ ๊ฐ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ UI๋ฅผ ์ ๋ฐ์ดํธ ํ ์ ์๋ค. ๋ ๋ฉ์๋๋ ์๋ฐํ๊ฒ ์ด์ผ๊ธฐํ์ฌ ํธ๋ค๋ฌ์์ ์ ๊ณตํ๋ ๋ฉ์๋์ด๋ฉฐ, ๋ชจ๋ Runnable ๊ฐ์ฒด๋ฅผ ๋งค๊ฐ ๋ณ์๋ก ์ฌ์ฉํ๋ค.
- ๊ฐ์ฒด์งํฅ ์๋ฆฌ๋ก ๋ฐฐ์ฐ๋ ์๋๋ก์ด๋ ํ๋ก๊ทธ๋๋ฐ (๋ฐํ์ฌ ์ง์) - 13์ฅ. ์ค๋ ๋์ ํธ๋ค๋ฌ
- ์๋๋ก์ด๋ ํ๋ก๊ทธ๋๋ฐ Next Step (๋ ธ์ฌ์ถ ์ง์) - 2์ฅ. ๋ฉ์ธ์ค๋ ๋์ Handler
- ์๋ฒฝํ ์๋๋ก์ด๋ ์ฑ์ ๋ง๋๋ ์ค๋ฌด ๋ ธํ์ฐ 139 (๊ฐ๋ ๋ง๋๋ถ, ์ค์นด์ค ์ธ 6๋ช ์ง์, ์ฅ๋ ๋ ์ฎ๊น)
- Efficient Android Threading, ์๋๋ก์ด๋ ๋ฉํฐ์ค๋ ๋ฉ (์๋ฐ๋ฅด์ค ์๋์ ์ง์, ํ๋ํฌ ์ฎ๊น)
-
์๋๋ก์ด๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ ๋ค๋ฃจ๊ธฐ Thread, Looper, Handler
(https://academy.realm.io/kr/posts/android-thread-looper-handler/)
โ