10 January 2017

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에 영향을 미치는 것이 아니라 앱이 종료될 염려는 없다.



blog comments powered by Disqus