티스토리 뷰
이전 포스팅에서 startService에 대해 설명했는데, startService에는 동기화 문제가 있다고 설명했다. 때문에 이를 대체할 IntentService라는 놈을 소개하겠다.
장점
1. 애초에 Sub Thread로 동작하기 때문에 별다른 Thread작업을 해주지 않아도 된다. (ANR 걱정 X)
2. 동기화 문제에 대해서 내부적으로 처리가 되어있어 신경쓰지 않아도 된다. (동기화 걱정 X)
여러 클라이언트에서 해당 Service를 시작시켜도, 순차적으로 동작하게끔 내부적으로 동기화 처리가 되어있다.
3. 구성이 간단하다. → Overriding해야하는 Method가 한개이다.
기존에 startService에서 onStartCommand에 Service에서 할 작업에 대해 작성했다면,
IntentService에서는 onHandleIntent(Intent intent)가 그 역할을 대체하게 된다.
Start Service를 사용한 코드와 Intent Service를 사용한 코드를 비교해서 살펴보겠다.
public class CountdownService extends Service {
int mCountdownNum = 0;
public int onStartCommand(Intent intent, int flags, final int startId) {
super.onStartCommand(intent, flags, startId);
mCountdownNum = intent.getExtras().getInt("COUNTDOWN_NUM");
new Thread("Countdown Thread") {
public void run() {
while(mCountdownNum > 0) {
Log.i("superroid", "start Id " + startId + " Countdown: " + mCountdownNum);
mCountdownNum--;
try{ Thread.sleep(1000); }
catch(InterruptedException e) { break; }
}
Log.d("superdroid", "stopSelf : " + startId);
// stopService없이 스스로 종료할 수 있도록 처리해주는 코드이다.
stopSelf(startId);
}
}.start();
return START_STICKY;
}
}
여러 클라이언트의 Service 시작 요청으로 onStartCommand 함수가 여러번 실행되고, 그에 따라 여러 개의 Thread가 생기게 될 수 있다.
여기서 mCountdownNum 인스턴스 변수는 스레드 내에 포함되지 않은 변수이기 때문에 여러 개의 Thread가 생기게되면 이를 공유하게 되고, 여기 접근함에 있어 동기화문제가 발생할 수 있는 것이다.
public void onClick(View v) {
switch(v.getId()) {
case R.id.countdown_3_btn:
Intent serviceIntent = new Intent("ch4njun_countdown");
serviceIntent.putExtra("COUNTDOWN_NUM", 3);
startService(serviceIntent);
break;
case R.id.countdown_5_btn:
Intent serviceIntent = new Intent("ch4njun_countdown");
serviceIntent.putExtra("COUNTDOWN_NUM", 5);
startService(serviceIntent);
break;
case R.id.countdown_7_btn:
Intent serviceIntent = new Intent("ch4njun_countdown");
serviceIntent.putExtra("COUNTDOWN_NUM", 7);
startService(serviceIntent);
break;
}
}
이 때 동시에 3개의 버튼을 누르게 되면 결과가 아래와 같이 출력된다.
동기화 문제가 발생한 것을 확인할 수 있다.
그럼 이와같은 문제를 Intent Service를 사용함으로써 해결하는 코드를 살펴보자.
onStartCommand 대신에 onHandleIntent를 Overriding해서 사용하게 된다.
public class CountdownService extends IntentService {
int mCountdownNum = 0;
public CountdownService() {
super("Countdown Service");
}
protected void onHandleIntent(Intent intent) {
mCountdownNum = intent.getExtras().getInt("COUNTDOWN_NUM");
while(mCountdownNum > 0) {
Log.i("superdroid", "Countdown : " + mCountdownNum);
mCountdownNum--;
try { Thread.sleep(1000); }
catch(InterruptedException e) { break; }
}
}
}
앞에서 말했듯이 알아서 Worker Thread상에서 동작하도록 되어있기 때문에 별도로 Thread처리를 하지 않아도 되는 것을 확인할 수 있다.
마찬가지로 결과를 확인해보면 동기화 문제가 해결된 것을 확인할 수 있다.
'Android > Concept' 카테고리의 다른 글
[Android] Android에서 프로젝트와 프로세스 ★★★ (0) | 2019.08.28 |
---|---|
[Android] Local Bound Service (Local Service) (0) | 2019.08.21 |
[Android] startService (Local Service) (0) | 2019.08.20 |
[Android] Service (0) | 2019.08.19 |
[Android] Thread Helper Class → AsyncTask ★★★ (0) | 2019.08.19 |