상세 컨텐츠

본문 제목

[Android]안드로이드 스레드 구현시 주의 사항

Android 개발

by mobile 2013. 9. 19. 22:47

본문

반응형

안드로이드 애플리케이션에서 일반 스레드를 통해 이미지를 다운로드 하거나, 시간이 걸리는 작업의 결과를 화면에 표시하기 위해 화면상의 값들을 직접 바꿔주려다 보면 대부분의 경우 CalledFromWrongThreadException 라는 에러 메시지와 부딪히게 된다.


안드로이드에서 제공되는 뷰나 뷰그룹에서 제공하는 메서드들은 '단일 스레드 모델'(single-threaded model)이기 때문에 메인 스레드내에서 구현해야 한다. 참고로 멀티스레드 형태로 구현 되지 않는 '단일 스레드 모델' 일명 Thread-Unsafe라 불러진다.


아래와 같이 두 가지 상반되는 개념적인 충돌이 발생하게 된다.

1) 하나의 메인 스레드에서 5초간의 응답이 없으면 발생하는 안드로이드 강제 종료 문제

2) GUI 구현에 있어 메인 스레드가 아닌 일반 스레드 구현시 발생하는 'CalledFromWrongThreadException'이라는 예외 발생


위의 두가지 문제는 일반적으로 팡에서 배웠던 핸들러를 사용하여 작업 시간이 오래 걸리는 작업 예를 들어 다운로드나 데이터베이스 작업등 시간이 소요 되는 것은 일반 스레드로 실행되고 메인 스레드에서 진행 다이얼로그를 사용 하거나 또는 웹브라우저처럼 타이틀바내 프로그레스바를 사용하여 진행사항을 화면에 출력시키는 방식으로 해결하게 된다.


물론 핸들러이위에 위의 문제를 해결하는 방법으로 안드로이드는 아래와 같은 메서드를 권장하고 있다.

- Activity.runOnUiThread(Runnable)

- View.post(Runnable) 또는 View.postDelayed(Runnable, long)


위에서 언급한 메서드들도 엄밀하게 이야기하여 액티비티나 뷰의 클래스를 상속받지만 안드로이드의 내부 핸들러로 구현되어 있다는 특징을 갖고 있다. 위의 메서드는 메시지 객체를 사용하는 것이 아니라 모두 Runnable 객체를 사용한다.


runOnUiThread() 메서드는 일반 스레드에서 Runnable 인터페이스를 구현하여 간단하게 작업을 수행하는 방법을 제공한다. runOnUiThread() 메서드는 스레드를 상속받아 처리하는 것보다 몇가지 이점을 제공한다.


http://android-developers.blogspot.kr/2009/05/painless-threading.html


// 잘못된 사용 법

public void onClick(View v) {
 
new Thread(new Runnable() {
   
public void run() {
     
Bitmap b = loadImageFromNetwork();
      mImageView
.setImageBitmap(b);
   
}
 
}).start();
}

// 수정

Any of these classes and methods could be used to correct our previous code example:

public void onClick(View v) {
 
new Thread(new Runnable() {
   
public void run() {
     
final Bitmap b = loadImageFromNetwork();
      mImageView
.post(new Runnable() {
       
public void run() {
          mImageView
.setImageBitmap(b);
       
}
     
});
   
}
 
}).start();
}

AsyncTask is also available for Android 1.0 and 1.1 under the name UserTask. It offers the exact same API and all you have to do is copy its source code in your application.

The goal of AsyncTask is to take care of thread management for you. Our previous example can easily be rewritten withAsyncTask:

public void onClick(View v) {
 
new DownloadImageTask().execute("http://example.com/image.png");
}

private class DownloadImageTask extends AsyncTask {
     
protected Bitmap doInBackground(String... urls) {
         
return loadImageFromNetwork(urls[0]);
     
}

     
protected void onPostExecute(Bitmap result) {
         mImageView
.setImageBitmap(result);
     
}
 
}



반응형

'Android 개발' 카테고리의 다른 글

[Android]서비스 - 01  (0) 2013.09.20
[Android]단일 스레드 모델  (0) 2013.09.19
[Android]핸들러 클래스  (0) 2013.09.19
[Android]스레드 구현  (0) 2013.09.18
[Android]사용자가 만든 토스트  (0) 2013.09.15

관련글 더보기

댓글 영역