Handler란?

  한 스레드는 그 내부의 연산만 가능하며 다른 스레드의 UI를 건드릴 수 없습니다.
 그런데 만약 스레드들이 서로 영향을 줄 수 없다면 스레드의 존재 이유가 없을 것입니다.

  이를 해결하기 위해서 서로 다른 스레드 간의 참조를 위해서 스레드 간에 통신할 
 수 있는 장치
를 만들었는데 그것이 핸들러[Handler]입니다.
 핸들러는 스레드 간에 메시지 객체나 러너블 객체를 통해 통신할 수 있는 장치이며,하나
 의 핸들러는 하나의 스레드와 관련을 맺습니다. 핸들러는 자신이 생성된 스레드에 짝이
 되며 다른 스레드와 통신을 수행하게 됩니다.

Handler의 메시지 수령
  핸들러에 메시지가 도착하게 되면 아래의 메서드가 호출됩니다.
 public void handleMessage(Message msg)
 인수로 메시지 객체를 전달 받는데 이는 스레드 간에 통신을 해야 할 내용에 관한 객체입
 니다. 몇가지 정보가 추가 될 수 있기 때문에 여러 개의 필드를 가지고 있습니다.

 메시지 필드 : 설명
 1. int what : Message의 ID
 2. int arg1 : Message가 보낼 수 있는 첫번째 정보.
 3. int arg2 : Message가 보낼 수 있는 두번째 정보.
 4 Object obj : Integer로 표현 불가능 할 경우 객체를 보냄.
 5. Messenger replyTo : 응답을 받을 객체를 지정.

Handler의 메시지 전송
  Message를 전송할 때는 다음의 메서드를 사용합니다.
 1. boolean Hanler.sendEmptyMessage(int what);
    - Message 의 ID에 해당하는 값을 전달할 때 사용함.
 2. boolean Handler.sendMessage(Message msg);
     - ID만으로 불가능하고 좀 더 내용이 있는 정보를 전송할 때 사용.
 3. boolean sendMessageAtFrontOfQueue(Message msg);
     - 메시지가 큐에 순서대로 쌓여서 FIFO(First In Frist Out)형태로 처리되지만,
       이 메서드를 사용하면 노래방에서 우선 예약 하듯이 사용가능합니다.

Handler의 발송과 수령 예제
//Handler 시작 부분
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        BackThread thread = new BackThread();
        thread.setDaemon(true);
        thread.start();
    }

//Handler Class
  class BackThread extends Thread {
 @Override
 public void run() {
  // TODO Auto-generated method stub
  while(true)
  {
   //처리 내용

   //핸들러 메세지 보내는 부분
   mHandler.sendEmptyMessage(0);
   try {
    Thread.sleep(1000);
   } catch (Exception e) {
    // TODO: handle exception
    ;
   }
  }
  };
  //핸들러를 받아서 처리할 내용
  Handler mHandler = new Handler() {
   public void handleMessage(android.os.Message msg)
   {
    if(msg.what == 0){
     //처리할 내용
    }
   };

 }
}


Handler의 객체 전송
  앞선 메서드로 특정 정보를 보낼 수 있지만 메시지를 보내는 대신에 객체를 보낼 수도
 있습니다.
 boolean post(Runnable r)
  핸들러로 다음의 매서드를 통해 Runnable 객체를 보내면 해당 객체의 run 메서드가
 실행됩니다. 이럴 경우 메시지를 받는 쪽은 다른 것을 정의하지 않고 핸들러만 정의하면
 해당 내용을 수행할 수 있습니다.

Handler의 객체 전송 예제
  class BackThread extends Thread {
 @Override
 public void run() {
  // TODO Auto-generated method stub
  while(true)
  {
   //처리 내용
   mHandler.post(new Runnable() {
    
    @Override
    public void run() {
     // TODO Auto-generated method stub
     // 객체를 받아서 처리할 내용
    }
   });
   try {
    Thread.sleep(1000);
   } catch (Exception e) {
    // TODO: handle exception
    ;
   }
  }
 }
 //핸들러를 받아서 처리할 내용
 Handler mHandler = new Handler();
}

클래스의 분리 시 메시지 교환
  앞선 예제처럼 스레드가 이너 클래스로 구현되었을 경우 멤버의 공유가 가능하지만 그렇
 지 않고 분리된 클래스의 경우에는 더 상세한 코드의 구현이 필요합니다.
  이경우 스레드는 전달 받은 핸들러를 자신의 멤버로 따로 저장해야 하고 (공유가 불가능
 하기 때문입니다.) 메시지 객체에 추가 정보를 저장해서 보내야 합니다.

클래스 분리시 메시지 교환 예제
  public class TestSampleProject extends Activity {
 
 int mManinValue = 0;
 int mBackValue = 0;
 TextView mMainText;
 TextView mBackTest;
 
 BackThread thread;
 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        thread = new BackThread(mHandler );
        thread.setDaemon(true);
        thread.start();
    }
   
    Handler mHandler = new Handler() {
     public void handleMessage(android.os.Message msg)
     {
      if(msg.what == 0)
      {
       //처리할 내용
      }
     };
    };
}

class BackThread extends Thread {
 Handler mHandler;
 
 public BackThread(Handler handler) {
  // TODO Auto-generated constructor stub
  mHandler = handler;
 }
 
 @Override
 public void run() {
  // TODO Auto-generated method stub
  Message msg = new Message();
  msg.what = 0;
  msg.arg1 = 1;
  mHandler.sendMessage(msg);
  try {
   Thread.sleep(1000);
  } catch (Exception e) {
   // TODO: handle exception
  }
 }
}

메시지 풀의 사용
  매번 핸들러를 구현할 때마다 new 연산자로 새로 생성한다면 메모리도 계속해서 사용할 것이고 그에 다른 가비지 컬렉션의 작업도 생길 것입니다. 이러면 속도도 느려지는 결과가 발생합니다.
이런 경우를 보완하고자 메시지 풀 이라는 임시 캐쉬를 유지시켜서 빠른 작업이 가능하게 합니다.
static Message obtain(message orig)
static Message obtain(Handler h, int what, int arg1, int arg2, Object obj)
 - obtain 메서드는 메시지 풀에서 비슷한 메시지가 있다면 이를 재사용하게 합니다.
void recycle()
 - 사용한 메시지를 풀에 집어 넣는 역할을 하는데 풀에 한번 집어 넣게 되면 시스템이 
   관리하므로 더 이상 관여할 수 없습니다.

메시지 풀의 사용 예제
...
class BackThread extends Thread {
 Handler mHandler;
 
 public BackThread(Handler handler) {
  // TODO Auto-generated constructor stub
  mHandler = handler;
 }
 
 @Override
 public void run() {
  // TODO Auto-generated method stub
  while(true)
  {
   //처리할 내용
   
   Message msg = Message.obtain(mHandler, 0 , 1 , 0);
   mHandler.sendMessage(msg);
   try {
    Thread.sleep(1000);
   } catch (Exception e) {
    // TODO: handle exception
   }
  }
 }
}


출처 : http://blog.naver.com/crowdark7?Redirect=Log&logNo=109201348

+ Recent posts