아마 안드로이드 어플리케이션을 개발하시면서 항상 한번은 거쳐가는 예외가 UI를 변경하려고 할때 나오는
CalledFromWrongThreadException 일텐데 일본웹쪽을 검색하다가 우연히 본내용을 바탕으로 한번
적어보겠습니다.
.
.
안드로이드의 UI는 단일 스레드 모델이기 때문에 UI단에서 스레드를 사용하고 싶다면 핸들러를 사용해야 합니다.
public void onClick(View v) { new Thread(new Runnable() { public void run() { txtView.setText("안녕하세요?"); // 텍스트뷰의 내용변경 } }).start(); }위와 같은 코드를 실행하게 된다면 해당코드는 다른스레드에서 UI에 접근하기때문에 CalledFromWrongThreadException 예외가 발생하게 되죠 이런 문제를 해결하기 위해 쓰는것이 바로 핸들러가 되겠습니다. 핸들러를 가지고 위의 코드를 수정해 보겠습니다.
Handler handler = new Handler(); public void onClick(View v) { new Thread(new Runnable() { public void run() { handler.post(new Runnable() { public void run() { txtView.setText("이제는 됩니다."); } }); } }).start(); }이렇게 Handler 인스턴스를 만들어놓고 post안에 Runnable을 구현하면 됩니다. post안에 Runnable을 구현하는 방법 외에도 많은 방법이 존재합니다. - CalledFromWrongThreadException 발생 원인 - 왜 다른스레드에서 UI를 변경하려고 하면 해당 예외가 발생하는지 안드로이드 기본소스를 통하여 알아보자면 UI변경이 있게되면 안드로이드 뷰에서는 invalidate를 호출하게 되는데
// View.java public void invalidate() { ... final ViewParent p = mParent; ... p.invalidateChild(this, r); }여기서 보게 되면 invalidate()에서는 ViewParent의 invalidateChild()를 호출하는군요
// ViewRoot.java public void invalidateChild(View child, Rect dirty) { checkThread(); ... } public checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( "Only the original thread that created a view hierarchy can touch its views."); } }invalidate()에서는 checkThread()를 호출합니다. checkThread()에서는 위와 같이 현재 실행중인 스레드가 ViewRoot가 가지고 있는 mThread와 참조가 같은지 비교하고 아니라면 CalledFromWrongThreadException 예외를 던지는군요 출처 : 안드로이드펍