๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๋นˆ ๊ตฌ๋ฉ ์ฑ„์šฐ๊ธฐ

[Android][๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ] Handler, HandlerThread ์ด์šฉํ•˜๊ธฐ

์ฐธ๊ณ 

์•ˆ๋“œ๋กœ์ด๋“œ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ฑ…

http://acornpub.co.kr/book/async-android

 

์•ˆ๋“œ๋กœ์ด๋“œ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

์ฑ…์€ ๋ฐ˜์‘ํ˜• ์•ฑ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ์•ˆ๋“œ๋กœ์ด๋“œ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์ฃผ์š” ๊ธฐ๋ฒ•

www.acornpub.co.kr

 

๊ฒฐ๋ก 

๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ž‘์—…ํ•˜๊ณ , ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ”์ธ์“ฐ๋ ˆ๋“œ๋กœ ๋ณด๋‚ด UI์— ์ถœ๋ ฅํ•˜๋Š” ๋ฐฉ๋ฒ•

> ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ์—์„œ์˜ ์ž‘์—…์„ Handler๋ฅผ ํ†ตํ•ด ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋กœ ๋ณด๋‚ด๊ธฐ 

 

๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ๋กœ ์ž‘์—… ๋ณด๋‚ด๊ธฐ, ํ˜น์€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ์—์„œ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋กœ ์ž‘์—… ๋ณด๋‚ด๊ธฐ

> Handler์™€ HandlerThread๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

์„ค๋ช…

๋ฃจํผ Looper ๋“ฑ์žฅ

๋ฃจํผLooper๋Š” ๋ฌด์—‡์ธ๊ฐ€?

์˜์›ํžˆ ๋ฐ˜๋ณตํ•˜๋Š” ํด๋ž˜์Šค. ํ์— ์ถ”๊ฐ€๋˜๋Š” ๋ฉ”์‹œ์ง€Message๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋‹ค๊ฐ€ Message๋ฅผ dispatchํ•œ๋‹ค. 

 

๋ฃจํผ ์Šค๋ ˆ๋“œ๋Š” ๋ฌด์—‡์ธ๊ฐ€?

์Šค๋ ˆ๋“œ ๋‚ด๋ถ€์—์„œ ๋ฃจํผ๊ฐ€ ์žˆ๊ณ , ๋ฃจํผ์˜ ์ •์  ๋ฉ”์†Œ๋“œ์ธ prepare์™€ loop๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

ํ•ธ๋“ค๋Ÿฌ๋กœ ๋ฃจํผ ์Šค๋ ˆ๋“œ ์•ˆ์˜ ํ์— ๋ฉ”์‹œ์ง€๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

 

ํ•ธ๋“ค๋Ÿฌ๋Š” ๋ฌด์—‡์ธ๊ฐ€?

1) ๋ฃจํผ์˜ ํ์— ๋ฉ”์‹œ์ง€๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ๋ฃจํผ์˜ ํ์— ๋ฉ”์‹œ์ง€๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์จ์•ผํ•œ๋‹ค๋Š” ์˜๋ฏธ๋กœ ์ดํ•ดํ•จ.

2) ๋ฃจํผ์˜ ๋ฉ”์‹œ์ง€๋ฅผ dispatchํ•  ๋•Œ ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ์ฝœ๋ฐฑ์„ ๊ตฌํ˜„ํ•œ๋‹ค.

 

๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋Š” ์‹ค์ œ๋กœ ๋ฃจํผ ์Šค๋ ˆ๋“œ์ด๋‹ค.

์•กํ‹ฐ๋น„ํ‹ฐ ์ƒ๋ช…์ฃผ๊ธฐ ์ฝœ๋ฐฑ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ชจ๋“  ์ผ์€ ๋ฉ”์ธ ๋ฃจํผ๊ฐ€ ํ˜ธ์ถœํ•œ dispatchMessage ํ˜ธ์ถœ์—์„œ ์ผ์–ด๋‚œ๋‹ค.

๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋กœ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.> ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ์˜ ์ž‘์—…์„ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋กœ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

 

๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ž‘์—…ํ•˜๊ณ , ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ”์ธ์“ฐ๋ ˆ๋“œ๋กœ ๋ณด๋‚ด UI์— ์ถœ๋ ฅํ•˜๋Š” ๋ฐฉ๋ฒ• > ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ์—์„œ์˜ ์ž‘์—…์„ Handler๋ฅผ ํ†ตํ•ด ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋กœ ๋ณด๋‚ด๊ธฐ

 

1)  ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์— ์ฒ˜๋ฆฌํ•˜๋Š” ์ž‘์—…์„ ์ œ์ถœํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ ๋งŒ๋“ค๊ธฐ. 

๋ฉ”์ธ ๋ฃจํผ ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ํ•ธ๋“ค๋Ÿฌ ์ƒ์„ฑ์ž์— ์ „๋‹ฌํ•˜๊ธฐ.

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Handler handler = new Handler(Looper.getMainLooper);
}

 

2-1) post๋ฅผ ์ด์šฉํ•˜๊ธฐ

handler.post(new Runnable() {
    public void run() {
        // ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ์ž‘์—… ์ˆ˜ํ–‰
    }
});

handler.postAtFrontOfQueue(new Runnable() {
    public void run() {
        // ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ์ž‘์—… ์ˆ˜ํ–‰
        // ํ์—์„œ ๋ฌด์—‡๋ณด๋‹ค๋„ ์šฐ์„ ์‹œํ•˜๋Š” Runnable๋กœ, ๊ธฐ์กด ์ž‘์—…๋ณด๋‹ค ์•ž์„œ๊ฒŒ๋” ํ์˜ ๋งจ ์•ž์— ๊ฒŒ์‹œํ•จ.
    }
});

handler.postDelayed(new Runnable() {
    public void run() {
        //10์ดˆ ์ง€์—ฐ ํ›„ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ์ž‘์—… ์ˆ˜ํ–‰
    }
}, TimeUnit.SECONDS.toMillis(10));

 

post๋กœ ๊ฒŒ์‹œํ•˜๋Š” Runnable์€ Message์˜ callback์œผ๋กœ ์ฐธ์กฐ๋˜๊ณ , ์ด Runnable์ด ์ฐธ์กฐ๋œ ๋ฉ”์‹œ์ง€๊ฐ€ ๋ฃจํผ์˜ ํ์— ์ถ”๊ฐ€๋œ๋‹ค. ๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ์ด Runnable์ด ์‹คํ–‰๋œ๋‹ค.

//Handler.java ์•ˆ

public final boolean post(@NonNull Runnable r) {
    return  sendMessageDelayed(getPostMessage(r), 0);
}

//post๋กœ ๋ฐ›์€ Runnable์„ Message์˜ callback์œผ๋กœ ์ฐธ์กฐํ•œ๋‹ค.
private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;
    return m;
}

public void dispatchMessage(@NonNull Message msg) {
    if (msg.callback != null) {
        //์—ฌ๊ธฐ๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

//post๋กœ ๋ฐ›์€ Runnable์˜ ์‹คํ–‰
private static void handleCallback(Message message) {
    message.callback.run();
}

 

2-1-1) ๊ธฐ๋‹ค๋ฆฌ๋Š” Runnable ์ทจ์†Œํ•˜๊ธฐ

Runnable ์ฝœ๋ฐฑ์„ Queue์—์„œ ์ œ๊ฑฐํ•ด์„œ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ž‘์—… ์ทจ์†Œ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค. ๋ฌด์—‡์„ ์ œ๊ฑฐํ• ์ง€ ์ง€์ •ํ•˜๊ธฐ ์œ„ํ•ด Runnable ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ์œ ์ง€ํ•˜๊ณ  ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ž‘์—…์—๋งŒ ์ทจ์†Œ๊ฐ€ ์ ์šฉ๋œ๋‹ค. ์ด๋ฏธ ์‹คํ–‰ ์ค‘์ธ Runnable์„ ์ค‘์ง€ํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค.

final Runnable runnable = new Runnable() {
    public void run(){
        // ... ์ž‘์—… ์ˆ˜ํ–‰
    }
}
handler.postDelayed(runnable, TimeUnit.SECONDS.toMilles(10));
...
handler.removeCallbacks(runnable);

 

2-2) send ์ด์šฉํ•˜๊ธฐ

post๋กœ Runnable๋กœ ์ž‘์—…์„ ๋ณด๋‚ด๋ฉด, ์ž‘์—…์— ๋Œ€ํ•œ ์‚ฌ์ „ ์ •๋ณด๋ฅผ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์•Œ ์ˆ˜ ์—†๋‹ค. ์ž‘์—…์— ๋Œ€ํ•œ ์‚ฌ์ „ ์ •๋ณด๋ฅผ ์•Œ๊ณ  ์ ์ ˆํ•˜๊ฒŒ ๋ฐ˜์‘ํ•  ์ˆ˜ ์žˆ๋„๋ก, ํ•ธ๋“ค๋Ÿฌ์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ณ , ๋ฉ”์‹œ์ง€์— ๋”ฐ๋ผ ์ ์ ˆํ•˜๊ฒŒ ๋ฐ˜์‘ํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ƒ์†ํ•˜๋Š” ๋ฐฉ๋ฒ•

public static class ReactionHandler extends Handler {
    public static final int WOW = 0;
    public static final int OOPS = 1;
    public static final int AWESOME = 2;
    
    @Override
    public void handleMessage(Message msg) {
        switch(msg.what) {
            case WOW:
                sayWord("wow");
                break;
            case OOPS:
                sayWord("oops");
                break;
            case AWESOME:
                sayWord("awesome");
                break;
            default:
                super.handlerMessage(msg);
        }
    }
    
    private void sayWord(String word) {...}
}


private Handler handler;
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    handler = new ReactionHandler(Looper.getMainLooper());
    ...
}

 

Hander.Callack์„ ์ƒ์†ํ•ด callback์œผ๋กœ ์กฐํ•ฉํ•˜๋Š” ๋ฐฉ๋ฒ•

public static class ReactionCallback implements Handler.Callback {
    public static final int WOW = 0;
    public static final int OOPS = 1;
    public static final int AWESOME = 2;
    
    @Override
    public boolean handleMessage(Message msg) {
        switch(msg.what) {
            case WOW:
                sayWord("wow");
                break;
            case OOPS:
                sayWord("oops");
                break;
            case AWESOME:
                sayWord("awesome");
                break;
            default:
                false;
        }
        return true;
    }
    
    private void sayWord(String word) {...}
}


private Handler handler;
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    handler = new Handler(Looper.getMainLooper(), new ReactionCallback());
    ...
}

 

๋‘ ๋ฐฉ๋ฒ•์„ ๋‘˜ ๋‹ค ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

๋ฉ”์‹œ์ง€ ๋ณด๋‚ด๋Š” ๋ฐฉ๋ฒ•

handler.sendEmptyMessage(AWESOME);


// Handler.java ์•ˆ

public final boolean sendEmptyMessage(int what)
{
    return sendEmptyMessageDelayed(what, 0);
}

//sendEmptyMessage๋กœ ๋ฐ›์€ int ๊ฐ’์ด Message์˜ what์œผ๋กœ ๋„ฃ์–ด์ ธ ํ์— ์ถ”๊ฐ€๋œ๋‹ค.
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
    Message msg = Message.obtain();
    msg.what = what;
    return sendMessageDelayed(msg, delayMillis);
}

 

๊ธฐ๋‹ค๋ฆฌ๋Š” ๋ฉ”์‹œ์ง€ ์ทจ์†Œํ•˜๋Š” ๋ฐฉ๋ฒ•

handler.removeMessage(AWESOME);

์ทจ์†Œํ•˜๊ธฐ๋ฅผ ์›ํ•˜๋Š” ๋ฉ”์‹œ์ง€์˜ ์ฐธ์กฐ๋ฅผ ์œ ์ง€ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. what ๋ณ€์ˆ˜๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๊ทธ๋ƒฅ ์ทจ์†Œํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

๋ฉ”์‹œ์ง€ ์ „์†ก vs Runnable ์ „์†ก ๋น„๊ต

์‹คํ–‰ ์‹œ๊ฐ„ ์ฐจ์ด : ํšจ์œจ์„ฑ์˜ ๋ฌธ์ œ

ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์›ํ•  ๋•Œ๋งˆ๋‹ค Runnable์˜ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜ ๊ณผ๋ถ€ํ•˜๋ฅผ ์ˆ˜๋ฐ˜ํ•˜๊ฒŒ ๋œ๋‹ค.

๋ฉ”์‹œ์ง€ ์ „์†ก์€ application-wide pool์—์„œ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฉ”์‹œ์ง€ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ณต๊ธ‰ํ•œ๋‹ค.

 

๊ฐœ๋ฐœ ์‹œ๊ฐ„ ์ฐจ์ด

Runnable์„ ์‚ฌ์šฉํ•˜๋ฉด Runnable.run ์ฝ”๋“œ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๋‹ค... ์‹œ๊ฐ„์ด ์ ๊ฒŒ ๊ฑธ๋ฆฐ๋‹ค...๊ณ  ์ฑ…์—์„œ ๋งํ•˜๋Š” ๊ฑฐ ๊ฐ™๋‹ค. 

๋ฉ”์‹œ์ง€ ์‚ฌ์šฉ์‹œ, ๋‹จ์ผ ์œ„์น˜(Handler.handleMessage)์—์„œ ์ค€๋น„ ์ž‘์—…์„ ์ •์˜ํ•ด์•ผ ํ•˜๋Š”๋ฐ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ๋‹ค.

 

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํ”„๋กœํ† ํƒ€์ž…์ด๊ณ , ์†Œ๊ทœ๋ชจ ๋‹จ๋ฐœ์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด Runnable ๊ฒŒ์‹œ๊ฐ€ ๋น ๋ฅด๊ณ  ์‰ฝ๋‹ค.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ทœ๋ชจ๊ฐ€ ์ปค์ง€๋ฉด ๋ฉ”์‹œ์ง€ ์ „์†ก์ด ์ข‹๋‹ค๊ณ  ํ•œ๋‹ค. ๋ฉ”์‹œ์ง€๊ฐ€ ๊ฐ€๋น„์ง€ ์ตœ์†Œํ™”๋ฅผ ์œ ์ง€ํ•˜๊ณ  ์•ฑ์„ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ํ”Œ๋žซํผ์œผ๋กœ ํ†ต์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋ผ๊ณ  ํ•œ๋‹ค.

 

๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ๋กœ ์ž‘์—… ๋ณด๋‚ด๊ธฐ, ํ˜น์€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ์—์„œ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋กœ ์ž‘์—… ๋ณด๋‚ด๊ธฐ > Handler์™€ HandlerThread๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

Handler์— HandlerThread์˜ ๋ฃจํผ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ.

HandlerThread thread = new HandlerThread("bg", Process.THREAD_PRIORITY_BACKGROUND);

thread.start(); // ๋ฐ˜๋“œ์‹œ ํ•„์š”

Handler handler = new Handler(thread.getLooper());

handler.post(new Runnable() {
   public void run() {
       //...๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ์—์„œ ์ž‘์—… ์ˆ˜ํ–‰
   }
});

 

ํŠน์ • ์•กํ‹ฐ๋น„ํ‹ฐ๋ฅผ ์œ„ํ•œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—…์„ ํ•˜๊ธฐ ์œ„ํ•ด, ์ž์› ๋ˆ„์ˆ˜๋ฅผ ๋ง‰๊ธฐ ์œ„ํ•ด ์•กํ‹ฐ๋น„ํ‹ฐ์˜ ์ƒ๋ช…์ฃผ๊ธฐ์— ๊ฐ€๊น๊ฒŒ HandlerThread์˜ ์ƒ๋ช…์ฃผ๊ธฐ์™€๋„ ๋ฌถ๊ธฐ

HandlerThread.quit์„ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ. HandlerThread๋ฅผ ์ข…๋ฃŒ์‹œ์ผœ์„œ ํ์˜ ์ž‘์—…์„ ๋” ์ด์ƒ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ํ•จ.

API ๋ ˆ๋ฒจ 18์—์„œ ์ถ”๊ฐ€๋œ quitSafety()๋Š” ์ข…๋ฃŒํ•˜๊ธฐ ์ „์— HandlerThread๊ฐ€ ๋‚จ์•„์žˆ๋Š” ๋ชจ๋“  ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•œ๋‹ค. ์ข…๋ฃŒ๋œ ๋‹ค์Œ์—๋Š” ์–ด๋–ค ์ž‘์—…๋„ ๋ฐ›์ง€ ์•Š๋Š”๋‹ค.

private HandlerThread thread;
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstatnceState);
    thread = new HandlerThread(...);
}

protected void onPause() {
    super.onPause();
    if ((thread != null) && (isFinishing())) {
        thread.quite();
    }
}

 

Handler๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๋‚˜์˜ค๋Š” ์ด์Šˆ

์•”์‹œ์  ์ฐธ์กฐ ๋ˆ„์ˆ˜

๋ฐœ์ƒ ์˜ˆ

//์•กํ‹ฐ๋น„ํ‹ฐ ๋‚ด๋ถ€์—์„œ ํ•ธ๋“ค๋Ÿฌ ์‚ฌ์šฉ
final Runnable runnable = new Runnable() {
    public void run() {
        // ...์ž‘์—… ์ˆ˜ํ–‰
    }
};

handler.postDelayed(runnable, TimeUnit.SECONDS.toMillis(10));

 

์•กํ‹ฐ๋น„ํ‹ฐ๊ฐ€ 10์ดˆ ์•ˆ์— ๋๋‚˜๋ฉด Runnable์„ ๊ฐ€๋น„์ง€๋ฅผ ์ˆ˜์ง‘ํ•  ์ˆ˜ ์—†๋‹ค. Runnable์˜ ์•”์‹œ์  ์ฐธ์กฐ๋Š” ๋ผ์ด๋ธŒ ๊ฐ์ฒดlive object๊ฐ€ ์—ฌ์ „ํžˆ ์•กํ‹ฐ๋น„ํ‹ฐ์— ์ ‘๊ทผํ•จ์„ ์˜๋ฏธํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

ํ•ด๊ฒฐ์ฑ…

  • ๋ฐฉ๋ฒ• 1: ๋น„์ •์  ๋‚ด๋ถ€ ํด๋ž˜์Šค ์‚ฌ์šฉ์„ ํ”ผํ•˜๋Š” ๊ฒƒ์ด๋‹ค. Runnable์„ ์ตœ์ƒ์œ„ ํด๋ž˜์Šค๋กœ ์„ ์–ธํ•˜๊ฑฐ๋‚˜, ์•กํ‹ฐ๋น„ํ‹ฐ ์„œ๋ธŒํด๋ž˜์Šค์—์„œ ์ •์  ํด๋ž˜์Šค(static)๋กœ ์„ ์–ธํ•˜๋Š” ๊ฒƒ. ์ฐธ์กฐ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค. 
  • ๋ฐฉ๋ฒ• 2:  onPause()์™€ ๊ฐ™์€ ์•กํ‹ฐ๋น„ํ‹ฐ ์ƒ๋ช…์ฃผ๊ธฐ ์ฝœ๋ฐฑ์—์„œ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ž‘์—…์€ ์ทจ์†Œํ•˜๊ธฐ
  • ๋ฐฉ๋ฒ• 3 : HandlerThread ์ธ์Šคํ„ด์Šค์˜ ๊ฒฝ์šฐ์—๋Š” ์•กํ‹ฐ๋น„ํ‹ฐ๋ฅผ ์ข…๋ฃŒํ•  ๋•Œ ์ฐจํ›„ ์‹คํ–‰์„ ๋ง‰๊ณ  ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜์„ ์œ„ํ•ด Runnable ๊ฐ์ฒด์™€ ๋ฉ”์‹œ์ง€ ๊ฐ์ฒด๋ฅผ ํ’€์–ด์ฃผ๋Š” quit์„ ๋ฐ˜๋“œ์‹œ ํ™•์ธํ•˜๊ธฐ

 

๋ช…์‹œ์  ์ฐธ์กฐ ๋ˆ„์ˆ˜

 

์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ์ค‘์—, ๋ทฐ ๊ณ„์ธต์˜ ๊ฐ์ฒด๋กœ ์ธํ•œ ์ฐธ์กฐ๋กœ ์ฐธ์กฐ ๋ˆ„์ˆ˜๊ฐ€ ์ผ์–ด๋‚  ์ˆ˜ ์žˆ๋‹ค.

 

๋ฐœ์ƒ ์˜ˆ

static class MyRunnable implements Runnable {
    private View view;
    public MyRunnable(View view) {
        this.view = view;
    }
    
    public void run() {
        //  ... ๋ทฐ์™€ ํ•จ๊ป˜ ์ž‘์—… ์ˆ˜ํ–‰
    }
}

๋ทฐ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ์œ ์ง€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— Runnable์ด ๋ทฐ๋ณด๋‹ค ๋” ์˜ค๋ž˜ ์ƒ์กดํ•œ๋‹ค๋ฉด ์ž ์žฌ์  ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋Œ€์ƒ์ด ๋œ๋‹ค.

 

ํ•ด๊ฒฐ์ฑ…

 

  • ๋ฐฉ๋ฒ• 1 : ์•ฝํ•œ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋˜, ์ฐธ์กฐ๋œ ๋ทฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ๋„์„ ํ™•์ธํ•œ๋‹ค.
static class MyRunnable implements Runnable {
    private WeakReference<View> view;
    public MyRunnable(View view) {
        this.view = new WeakReference<View>(view);
    }
    
    public void run() {
        View v = view.get(); // ๋„์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜๋„ ์žˆ์Œ
        if(v != null) {
            //  ... ๋ทฐ์™€ ํ•จ๊ป˜ ์ž‘์—… ์ˆ˜ํ–‰
        }
    }
}

 

 

  • ๋ฐฉ๋ฒ• 2 : ๋ฉ”์‹œ์ง€ ์ „์†ก์„ ์ด์šฉํ•œ๋‹ค๋ฉด, onResume๊ณผ onPause์—์„œ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋ถ™์ด๊ณ  ๋–ผ๋‚ด๊ธฐ
private static class MyHandler extends Handler {
    private TextView view;
    public void attach(TextView view) {
        this.view = view;
    }
    publci void detach() {
        view = null;
    }
    @Override
    public void handleMessage(Message msg) {
        //...
    }
}