마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

안드로이드 쓰레드 질문입니다.

0 추천

제가 메뉴에서 어떤 버튼을 누르면 큰 작업이 수행되게 프로그램을 만들었습니다.

그래서 그 작업을 쓰레드로 돌리고, 쓰레드 전에 프로그레스 바를 넣었습니다.

그런데 문제는 프로그레스 바가 반바퀴 돌다가 프로그레스 바도 죽는다는데 있죠...

원인을 모르겠어요. 큰작업은 쓰레드에서 돌아갈텐데... 왜 메인 쓰레드가 죽는지...

 

전체적인 흐름은..

메뉴 버튼 클릭-> 파일 선택 -> 프로그레스 바 호출 -> 쓰레드 작업 실행 -> 쓰레드 완료 -> 프로그레스 바 종료

이런건데

쓰레드 작업 중에 프로그레스바도 죽는게 문제입니다.

소스를 간단히 적으면 아래와 같습니다.

 

// DIALOG_1 부분은 메뉴 클릭시 나오는 다이얼로그
// DIALOG_PROGRESS 는 프로그레스 바 호출

protected Dialog onCreateDialog(int id) {
  switch (id) {
  case DIALOG_1:
   return new AlertDialog.Builder(MainActivity.this)
     .setTitle("파일을 선택하세요")
     .setItems(arr, new DialogInterface.OnClickListener() {
      @Override
      public void onClick(DialogInterface dialog, int which) {
       selectedFile = arr[which];
       showDialog(DIALOG_PROGRESS);
       myThread th = new myThread();
       th.setDaemon(true); 
       th.start(); 
      }
     }).setNegativeButton("닫기", null).create();
  case DIALOG_PROGRESS:
   mProgressDialog = new ProgressDialog(MainActivity.this); 
   mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
   mProgressDialog.setMessage("loading..");
   mProgressDialog.setCancelable(true);
   return mProgressDialog;
  }
  return null;
 }

public class myThread extends Thread {
  public void run() {
   try {
    Thread.sleep(1000);
    // 1000을 주지 않으면 아예 프로그레스바도 호출되기 전에 멈춰버리더군요;;
    handler.sendEmptyMessage(0);

   } catch (InterruptedException e) {
    // TODO 자동 생성된 catch 블록
    e.printStackTrace();
   }
  }
 }

 Handler handler = new Handler() {
  @Override
  public void handleMessage(Message msg) {
   // TODO Auto-generated method stub
   if (msg.what == 0) {
    longTime(selectedFile);
    dismissDialog(DIALOG_PROGRESS);
    mProgressDialog.dismiss();

   }
  }
 };

 

빨간 부분이 프로그레스 바와 쓰레드 사용 부분인데요.

longTime이 메인 작업입니다.

longTime 작업시 UI 를 건드리기 때문에 핸들러를 사용했습니다.

이 작업이 시간이 오래 걸리다보니 쓰레드 처리하고 프로그레스 바를 보여주는건데

죽어버리니 아무 소용이 없더군요 ㅠㅠ 이거 왜 이럴까요;;

 

시험모드 (970 포인트) 님이 2013년 3월 8일 질문

4개의 답변

0 추천
 
채택된 답변
이건 쓰레드에서 작업하는게 아닌데요...

무늬만 쓰레드를 실행시키고 실제는 쓰레드 밖에서 작업하는겁니다....

handlerMessage에서 작업하는건 쓰레드에서 작업하는게 아닙니다.
jelly (1,630 포인트) 님이 2013년 3월 8일 답변
시험모드님이 2013년 3월 8일 채택됨
헉.. 그렇군요 ㅡㅡ;
그럼.. longTime을 쓰레드로 넣고 쓰레드 에서 작업하다가
UI 건드는 부분에서 핸들러로 메시지를 보내야 하나요?
얼룩돼지님이 상세하게 설명해주셨네요 ㅎㅎ;;
아.. 근데 제가 하는 작업은 String형을 넘겨줘야 하는데요..
핸들러로 String 넘기려면 어떤 함수를 호출해야 되죠.
다 int 아니면 msg라고만 떠서 ㅠㅠ
String도 Object라소 obj로 넘기시면 됩니다. 클래스를 하나 만들어서 클래스를 넘기셔도 되구요
0 추천
데이터처리부분이 handler 쪽에 있어서 그렇습니다.

Thread에서 Handler를 사용하는 이유는 UI에 변경사항을 업데이트 하려면 UI쓰레드 즉 메인쓰레드에서

작업하기위함입니다.

UI쪽에 변화를 주고자할때 메인쓰레드가 아닌 쓰레드에서 작업을 하면 에러가 나기때문이죠

그런데 질문자분께서는 아마도 longTime(selectedFile); 이부분이 데이터작업하는 부분같은데

이메소드를 Handler에서 작업 즉 메인쓰레드에서 작업하였기때문입니다.

longTime(selectedFile);를 쓰레드 쪽에서 해보세요
얼룩돼지 (15,720 포인트) 님이 2013년 3월 8일 답변
후와... 감사합니다.
이제 알것 같네요 ^^;
0 추천
코드를 보니

아직 핸들러의 개념에 대해서 익숙하시지 않으신 것 같네요.

핸들러도

ANR에 대해서도 한번 찾아보시기 바랍니다.

 

현재 오래 걸리는 작업이 메인 쓰레드를 점유하고 있습니다.

그 작업을 쓰레드로 빼주신 후 쓰레드 실행시작 후나 직전에 다이얼로그를 띄워주시고,

쓰레드 작업이 끝난 시점이나 후에 다이얼로그를 닫아주시면 될것 같습니다.

 

핵심은 쓰레드에 큰 작업을 넣지 않으셨다는것에서 이미 큰작업이 메인 UI쓰레드를 계속 점유하는

상황이 되어 ANR이 발생된것입니다.
갸아악 (21,260 포인트) 님이 2013년 3월 8일 답변
아구 머리야 ㅠㅠ
핸들러가 소스는 간단해 보이는데 어렵네요 ㅠㅠ

ANR 찾아볼게요
0 추천
Asynctask 사용도 한번 생각해 보세요~~~^^
wind (2,240 포인트) 님이 2013년 3월 8일 답변
흑.. 또 새로운게 ㅠㅠ
감사합니다 ㅠㅠ
...