Home » Android -11. Thread와 Handler

Android -11. Thread와 Handler

11.1. Thread

<step9/ThreadSample>
[php]
Thread changeTextView1 = new Thread(start1);
Thread changeTextView2 = new Thread(start2);
// activity가 종료되면 쓰레드도 종료시킴
changeTextView1.setDaemon(true); (1)
changeTextView2.setDaemon(true);
changeTextView1.start(); (2)
… 생략

private Runnable start1 = new Runnable() {
public void run() {
final int total = 150;
while(count1 < total) {
try {
// UI 작업은 handler에서 처리, 핸들러로 메세지를 보냄
handler1.sendMessage(handler1.obtainMessage()); (3)
Thread.sleep(100);
} catch(final InterruptedException e) {
return;
} catch(final Exception e) {
return;
}

}
}
};

Handler handler1 = new Handler() {
public void handleMessage(Message msg) { (4)
count1++;
threadSampleTextView1.setText(""+count1);
if(count1 == 150) {
if(changeTextViewThread1 != null) {
changeTextViewThread1.interrupt();
}
}
};
};
[/php]

번호 설명
(1) Activity가 종료되게 되면 쓰레드도 종료시키는 설정
(2) 쓰레드 시작
(3) 0.1초마다 핸들러로 메시지 보냄
(4) 메시지가 왔을 때 호출 되는 메소드로 UI처리

11.2. Handler

  • 안드로이드는 기본적으로 메인 쓰레드에서의 UI 작업이 불가능하기 때문에 Handler라는 것을 통해 UI 작업을 처리한다.

[php]
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) { (1)
Intent intent = new Intent(HandlerSample.this, HandlerSample2.class);
startActivity(intent); (2)
finish();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.handler_sample);
ToastUtil.show(HandlerSample.this, "intro 화면입니다. 5초뒤 메인화면으로 이동합니다.");
// 5초 뒤에 다른 액티비티로 이동
handler.sendEmptyMessageDelayed(0, 5000); (3)
}
[/php]

번호 설명
(1) 메시지를 받는 메소드
(2) 설정 된 Activity로 이동 delay 5초를 주었기 때문에 5초 뒤 이동
(3) 핸들러에 메시지를 보내며 5초간 딜레이를 준다.

11.3. AsyncTask

  • 안드로이드에는 UI 를 총괄하는 메인Thread가 존재 하고 있는데, 메인Thread 외에는 일반Thread들이 안드로이드 UI 화면을 처리할 수 없다. 그렇기 때문에 메인Thread와 일반Thread 를 잘 핸들링 해서 사용해야 하는데 상당히 불편하다.
  • 그렇기 때문에, Android 에서는 AsyncTask 라는 객체를 지원한다. AsyncTask는 UI 처리 및 Background 작업 등을 하나의 클래스에서 작업 할 수 있게 지원 해 준다.
  • 쉽게 말해 메인 Thread와 일반 Thread를 가지고 Handler를 사용하여 핸들링하지 않아도 AsyncTask 객체 하나로 편하게 UI를 수정 할 수 있고, Background 작업을 진행 할 수 있다.

<step9/AsyncTaskSample>
[php]
new AccumulateTask().execute(100); (1)
… 생략
class AccumulateTask extends AsyncTask<Integer, Integer, Integer> { (2)
// execute 실행시 가장 먼저 수행되며 MainThread에서 수행.
protected void onPreExecute(){ (3)
// dialog 설정
mValue = 0;
mProgress = new ProgressDialog( mContext );
mProgress.setProgressStyle( ProgressDialog.STYLE_HORIZONTAL );
mProgress.setTitle( "Updating" );
mProgress.setMessage( "Wait…" );
mProgress.setCancelable( false );
mProgress.setProgress( 0 );
mProgress.show();
}

// 다른 Thread에서 수행되며, onPreExecute() 후 수행.
// arg0 에는 execute( params ) 에서 전달한 100 이 들어온다.
protected Integer doInBackground(Integer… arg0){ (4)
while ( isCancelled() == false ){
mValue++;
if ( mValue <= 100 ){
// onProgressUpdate() 가 불린다.
publishProgress( mValue );
}else{
break;
}

// 다운로드 하는것처럼 위장
try { Thread.sleep(50); } catch (InterruptedException e) { ; }
}
return mValue;
}

// doInBackground() 에서 publishProgress를 호출했을 때 Main Thread에서 수행.
// progress 에는 publishProgress( params ) 에서 전달한 mValue 값이 넘어온다.
protected void onProgressUpdate( Integer… progress ){ (5)
mProgress.setProgress(progress[0]);
asyncTaskSampleText.setText(Integer.toString(progress[0]));
}

// doInBackground() 작업이 끝나면 호출되며, MainThread에서 작업 수행
// result 값은 doInBackground() 의 Return 값이 들어온다.
protected void onPostExecute(Integer result){ (6)
mProgress.dismiss();
}
// cancel 되었을 때 호출된다.
protected void onCancelled(){ (7)
mProgress.dismiss();
}
}
[/php]

번호 설명
(1) 백그라운드 작업 시간
(2) AsyncTask를 상속 (인자에 대한 설명은 아래 참고)
(3) execute 실행시 가장 먼저 수행되며 MainThread에서 수행.
(4) onPreExecute() 후 수행. 실제 작업이 이루어지는 곳
(5) doInBackground() 에서 publishProgress를 호출했을 때 수행. 프로그레스바의 제어
(6) doInBackground() 작업이 끝나면 호출. 다이얼로그의 종료 등
(7) cancel 되었을 때 호출

  • 첫번째 인자는 execute()시에 넘겨 받을 인자를 정의.
    doInBackground()에서 호출될 때 값이 넘어가게 되며 여러 개의 값을 넘겨받을 수 있도록 되어있다. 다수의 값을 처리하도록 할 수 있다.

  • 두번째 인자는 onProgressUpdate()가 호출 될 때 넘겨받을 인자를 뜻한다.
    마찬가지로 publishProgress()를 통해 넘겨줄 인자이기도 하다. 마찬가지로 다수의 인자를 넘겨받을 수도 있으며 위의 예제에서는 단순히 ProgressBar를 증가시키는 것밖에 안 하기 때문에 1개의 Integer형만을 받도록 했다.

  • 세번째 인자는 onPostExecute()가 호출 될 때 넘겨받을 인자를 뜻한다.
    작업이 끝날 때 어떤 작업이 끝났는지를 알려주고 싶다거나 하면 그 작업 이름을 넘겨준다.
    이와 같이 작업이 끝났을 때 무언가 처리를 하고 싶은데 이것을 작업 수행 시점에 넘겨주고 싶다면 이 세번째 인자를 사용한다.