@markdown


![소개](https://t1.daumcdn.net/cfile/tistory/217ADD35595D0EB319)


# [Android] Handler, HandlerThread, AsyncTask

_

## Handler

_

안드로이드 메세지 핸들러

_

[Handler | Android Developers](https://developer.android.com/reference/android/os/Handler.html)

_

### 사용법

_

```java

Handler mHandler = new Handler() {

@Override

public void handleMessage(Message msg) {

if (msg.what == Constants.WHAT_MESSAGE) {

// TODO UI process

}

}

}


public void mainThreadWork() {

someThreadWork(mHandler);

}


public void someThreadWork(final Handler mHandler) {

new Thread(new Runnable() {

@Override

public void run() {

// TODO Some another thread work

// If done this process

Message msg = new Message();

msg.what = Constants.WHAT_MESSAGE;

mHandler.sendMessage(msg);

}

}).start();

}

```

_

기본적인 구조는 

1. Handler를 만들고 

2. 다른 쓰레드에서 작업후

3. 해당 Handler를 사용해 message 를 보내고

4. UI 쓰레드에서 필요한 작업을 진행하는 것이다.

_

### 설명

_

Handler는 다른 쓰레드에서 UI Thread 의 작업이 필요할 경우 사용되는 방법 중 하나이다.

Callback 구조를 알고 있다면 그 구조와 비슷한 형태임을 알 수 있다.

_

```java

// 콜백 인터페이스 생성

interface MyCallback {

void done(int arg1, int arg2);

}


MyCallback myCallback = new MyCallback() {

@Override

public void done(int arg1, int arg2) {

// TODO Main thread process

// 콜백이 호출 되었을때 진행됨

}

}


// 메인쓰레드에서 다른 쓰레드 호출

public void mainThreadWork() {

someCallbackWork(myCallback);

}


// 쓰레드 작업 완료후 콜백 반환

public void someThreadWork(final MyCallback callback) {

new Thread(new Runnable() {

@Override

public void run() {

// TODO Some another thread work

// If done this process

// 콜백을 통해 반환

callback.done(1, 2);

}

}).start();

}

```

_

이처럼 Callback과 비슷한 형태로 만들어진 Handler 에서는 Message 를 다룰 수 있는 부가적인 메서드들이 포함되어 있다.

_

이러한 Handler 가 필요한 이유는 UI Thread 를 Blocking 하지않고 비동기적인 작업을 할 수 있도록 제공하기 때문이다. 즉, UI 작업과 다른 작업을 분리하기 위함인데, 안드로이드에서는 Handler를 응용한 다양한 클래스 들을 제공하고 있다.

_

## HandlerThread

_

위와 같은 구조를 응용해서 만들어진 것이 바로 HandlerThread 이다.

_

[HandlerThread | Android Developers](https://developer.android.com/reference/android/os/HandlerThread.html)

_

### 사용법

_

```java

private Handler mHandler;

private HandlerThread handlerThread;


@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);


handlerThread = new HandlerThread("Handler Thread");

handlerThread.start(); // 여기서 쓰레드를 실행시켜둔다.

// Handler 를 새로 만들때 HandlerThread의 Looper를 넣어준다.

mHandler = new Handler(handlerThread.getLooper()) {

@Override

public void handleMessage(Message msg) {

if(msg.what == Constants.CLICKED) {

// TODO Background work

}

}

}

Button sendToHandlerThread = (Button) findViewById(R.id.send);

sendToHandlerThread.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

// 만들어둔 핸들러를 이용하여 다른 쓰레드에 메세지를 보낸다.

Message msg = mHandler.obtainMessage();

message.what = Constants.CLICKED;

mHandler.sendMessage(msg);

}

});

}


@Override

public void onDestroy() {

// HandlerThread는 백그라운드에서 Looper가 계속 돌고 있으므로 별도로 종료시켜 주어야 한다.

handlerThread.quit(); 

super.onDestroy();

}

```

_

### 설명

_

HandlerThread 는 안드로이드 백그라운드에서 돌며 순차적으로 메세지를 처리할 수 있는 MessageQueue를 제공한다.

사용방법은 

1. 내부적으로 구현된 Looper를 통해 먼저 쓰레드를 실행시키고

2. 외부에서 선언된 Handler를 이용해 메세지를 받고

3. 백그라운드 작업을 실시한다.

4. 일정 작업후 quit() 호출을 하여 명시적으로 Looper를 종료시킨다.

_

이렇게 HandlerThread 를 이용하게 되면 좀더 편리하게 쓰레드를 구분할 수 있다.

_

## AsyncTask

_

AsyncTask 도 위와 같이 Handler와 백그라운드 쓰레드를 이용한 비동기 처리를 위해 사용되는 클래스이다.

_

[AsyncTask | Android Developers](https://developer.android.com/reference/android/os/AsyncTask.html)

_

### 사용법

_

```java

TextView networkTextView;


@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Button networkButton = (Button) findViewById(R.id.send);

networkTextView = (TextView) findViewById(R.id.net_response);

// 버튼 클릭시 네트워크 작업을 실행시킨다.

networkButton.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

new AsyncTask<String, Void, String>() {

@Override

protected String doInBackground(String... urls) {

// AsyncTask Thread

// 네트워크 요청을 하고 응답메세지를 반환한다.

return someNetworkWork(urls[0]);

}

@Override

protected void onPostExecute(String responseMessage) {

// UI Thread

// 반환된 응답 메세지를 TextView에 반영한다.

netwrokTextView.setText(responseMessage);

}

}.execute("http://test.url.com/test");

}

});

}

```

_

### 설명

_

AsyncTask 의 doInBackground() 에서는 쓰레드를 생성하여 백그라운드 작업을 실행하고

작업이 끝난후 onPostExecute() 에서 UI 쓰레드로 전달된다. 

이 쓰레드는 UI 쓰레드 이므로 TextView 를 변경하는 등의 작업이 가능해진다.

위에서 설명한 방법에 비해서 훨씬 간결해진 문장을 볼 수 있다.

_

## 결론

_

Handler, HandlerThread, AsyncTask 의 기본적인 사용법과 안드로이드에서 백그라운드 작업하는 방법을 보았다.

이들 각각의 장단점이 있기 때문에 어느것이 더 나은 것이라기 보다 상황에 따라서 적절하게 사용하는 것이 좋다.

안드로이드는 UI Thread 가 MainThread 이고 이 안에서 할 수 있는 작업이 한정되어 있기 때문에 쓰레드를 적절히 생성해서 작업을 해야한다. 

_

다만 주의할 점은 다른 쓰레드에서도 Context 가 필요한 상황이 생기는데, 이때 쓰레드로 Context를 전달해주게 되는데, 여기서 쓰레드가 정확히 종료되지 않으면 Memory Leak이 발생하게 된다.  이는 다음 글에서 다루어 보도록 한다.

_

'android' 카테고리의 다른 글

[Android] 안드로이드의 SWAP  (0) 2017.07.18

+ Recent posts