UI 쓰레드가 아닌 일반 쓰레드에서 UI 작업처리를 위해 new Handler() 를 통해 Handler를 사용할 경우 아래와 같은 에러가 발생합니다.


java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()


그럼 UI처리를 위한 Handler는 UI 쓰레드에서만 생성해야 한다고 생각할 수 있습니다.

http://huni.springnote.com/pages/5402287



그러나 그렇지 않습니다. 임의의 쓰레드에서도 UI작업용 Handler를 사용할 수 있습니다.

http://blog.naver.com/PostView.nhn?blogId=rgjoon&logNo=90094338577



다만, UI 작업을 처리하기 위해서는 아래와 같이 UI쓰레드에 바인딩된 Handler를 만들어야 합니다.

http://stackoverflow.com/questions/6369287/accessing-ui-thread-handler-from-a-service


Handler handler = new Handler(Looper.getMainLooper());




* 참고

http://www.aviyehuda.com/2010/12/android-multithreading-in-a-ui-environment/

http://babtingdev.tistory.com/276


Posted by 에코지오
,

안드로이드는 스윙과 마찬가지로 싱글 쓰레드 GUI 모델이 적용되어 있다.
즉 UI를 그리거나 갱신하는 쓰레드는 하나뿐이라는 것이다. 그 쓰레드는 바로 안드로이드의 주요 컴포넌트들이 실행되는 "main" 쓰레드이다. 모든 UI 관련 코드는 main 쓰레드에서 실행된다.

스윙에서 응답없음(unresponsive) 현상을 막기 위해 백그라운드에서 돌아가는 worker 쓰레드를 만든 것처럼, 안드로이드에서도 오래 걸리는 작업은 UI 쓰레드(= main 쓰레드)에서 처리하지 말고 별도의 쓰레드를 만들어 처리해야 한다. 그렇지 않으면 화면을 갱신하고자 하는 모든 코드는 block 당하여 ANR이 발생할 것이다.

오래 걸리는 작업에는 무엇이 있나?
- 파일 처리
- 네트워크 조회
- 다량의 DB 트랜잭션
- 복잡한 계산

그럼 백그라운드 쓰레드(Worker Thread)를 만드는 방법은?
- UI 쓰레드와 상호작용 없으면 그냥 Thread.start()에서 처리하면 된다.
- 그러나 작업후 결과를 UI에 반영(즉 UI 쓰레드와 통신)해야 한다면 Handler 등을 이용해야 한다.

다른 쓰레드에서 UI 쓰레드에 액세스하는 방법

  • Handler : 일반적인 쓰레드간 상호작용
  • Activity.runOnUiThread(Runnable) : UI 쓰레드의 메시지큐에 작업을 전달(post).
       activity 인스턴스에 액세스할 수 있는 경우 사용
  • View.post(Runnable) : UI 쓰레드의 메시지큐에 작업을 추가. 해당 view 객체에 접근가능한 경우 사용
  • View.postDelayed(Runnable, long) : 일정시간 후에 작업 처리
  • AsyncTask : 쓰레드나 Handler에 대한 지식없이 백그라운드 작업 후 UI 쓰레드에서 화면갱신 작업을
       처리할 수 있게 코드를 단순화해주는 유틸리티 클래스
  • AsyncQueryHandler : 비동기적으로 쿼리를 수행할 수 있게 해주는 도우미 클래스
  • NotifyingAsyncQueryHandler
  • WeakAsyncTask

  • Handler는 무엇인가?
    - 쓰레드간 상호작용을 위한 일반적인 목적의 클래스
    - 작업 쓰레드(=자식 쓰레드)에서 부모 쓰레드(=Handler 객체를 생성한 쓰레드)에 Message 및
      Runnable(부모 쓰레드에서 처리할 작업) 전달(send/post 메소드)
    - 자식 쓰레드에서 handler를 통해 전달되는 Message와 Runnable은 부모 쓰레드의 메시지큐에 들어감
    - 내부적으로 Runnable도 결국은 Message로 변환(Message.callback=runnable)되어 메시지큐에 들어감
    - Handler 객체를 생성한 쓰레드(부모 쓰레드)에서는 Looper를 통해 MessageQueue를 만들어 놓아야 함
    - UI쓰레드(= main쓰레드)는 ActivityThread.main()에 의해 생성되는데, 여기서 Looper를 통해
      UI 쓰레드용 메시지 큐가 이미 만들어져 있으므로 우리가 UI 쓰레드용 메시지큐를 만들 필요는 없음
    - HandlerThread 클래스는 Looper를 가진 쓰레드를 쉽게 만들기 위한 용도


    * 안드로이드 쓰레드에 대한 'i티거'님의 글 참조

    http://tigerwoods.tistory.com/26 Thread 구현하기1

    http://tigerwoods.tistory.com/28 Thread 구현하기2

    Posted by 에코지오
    ,