Android 비동기 처리에 대한 정리
이 문서는 Android 非同期処理についてまとめるメモ를 번역하여 작성하였습니다.
Android에는 UI에 영향을 주지 않도록 여러 비동기 API들이 준비되어있다. 비동기 처리의 대표적인 API인
들에 대한 차이를 비교하며 정리한다.
Service & IntentService
■ Service
- 장점
- Activity에 의존하지 않고 장시간 백그라운드 처리에 적합하다.
- Context를 가지고 있다
- 단점
- 메인 스레드에서 동작하기 때문에 작업을 수행하면 화면의 응답이 늦어지거나 앱이 종료된다.
※ Service의 우월성
- Service는 Activity와 동일한 스레드에서 동작하고 있기 때문에 Service를 사용하지 않고 Acitivty에서 스레드를 생성하면 될 것이라 생각 할 수도 있지만 Service는 Context를 보유하고 있다.
- Activity에서도 스레드 생성 처리를 할 수 있지만, Activity가 종료되면 Activity에 관련된 Context를 사용 할 수가 없기 때문에 Context를 이용한 백그라운드 작업은 Service에서 처리해야한다.
■ IntentService
- 장점
- Activity에 의존하지 않고 비동기 처리에 적합하다.
- 내부에 HandlerThread을 가지고 있기 때문에, 메인 스레드는 다른 스레드 형태로 순처 처리를 한다.
Service와 IntentService의 차이점
아래에 Service를 사용한 처리 및 IntentService를 사용한 예제 코드를 작성한다. Activity에서 Intent를 사용하여 Service·IntentService를 호출한다.
- Activity
public class MainAcitivty extends AppCompatActivity implements View.OnClickListener { @Override protected void onCreate (Bundle savedInstanceState) { super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); findViewById(R.id.button_service).setOnClickListener(this); findViewById(R.id.button_intentservice).setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.button_service: Intent intent = new Intent(this, MyService.class); intent.setAction("show"); startService(intent); break; case R.id.button_intentservice: Intent intent = new Intent(this, MyIntentService.class); intent.setAction("show"); startService(intent); break; } } }
- Service(무한 for문을 실행)
public class MyService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { // 무한 for문을 실행 return START_NOT_STICKY; } }
→ 앱이 종료된다.
- IntentService(무한 for문을 실행)
public class MyIntentService extends IntentService { @Override protected void onHandleIntent (Intent intent) { // 무한 for문을 실행 } }
→ UI(메인 스레드)에 영향을 주지 않기 때문에 앱이 종료되지 않는다.
HandleThread
HandleThread는 내부에 Looper를 가지고 Handler에 의해 보내진 메시지를 순차적으로 처리하는 구조다.
Looper & Handler
■ Looper
- 내부에 Message Queue를 가지고 순서대로 Queue에서 꺼낸 메시지를 처리하는 방법
- Android의 기본적인 구조로 되어 Activity와 Service등이 Looper에서 동작하고 있음
- Activity와 Service는 메인 루퍼(메인 스레드)에서 동작하며 화면에 대한 위젯 변경등은 메인 루퍼에서 해야함
■ Handler
- Looper에 Message를 전달하기 위한 메신저
Handler와 HandlerThread의 차이점
Handler는 메인 스레드에서 작업이 진행된다. 하지만 HandlerThread는 새로운 Thread를 생성하고, 거기서 작업을 처리한다.
public class HandlerDefault extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_default);
Handler handler = new Handler();
handler.post (new Runnable() {
@Override
public void run() {
// 코스트 높은 작업을 수행
final String currentThread = Thread.currentThread().getName();
}
});
}
}
→ currentThread는 main 메인 스레드에서 코스트가 높은 작업을 수행하면 앱이 종료
public class HandlerThreadDefault extends AppCompatActivity {
@Override
protected void onCreat (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_thread_default);
// other 스레드 생성 -> 시작
HandlerThread handlerThread = new HandlerThread("other");
handlerThread.start();
// other 스레드의 Looper를 Handler에 할당
Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable() {
@Override
public void run() {
// 코스트 높은 작업을 수행
final String currentThread = Thread.currentThread().getName();
}
});
}
}
→ currentThread는 other 다른 스레드를 생성했기 때문에 코스트가 높은 작업을 수행하도 UI에 영향을 미치는 것이 아니라 앱이 종료될 염려는 없다.