Handler 사용하는 이유

업데이트:

Android에서 handler 사용하는 이유을 알아보고자 합니다.

스레드를 통해, 어떠한 동작(e.g. 통신, 계산)을 처리한 후, 결과 값은, 해당 스레드에서는 그림(setText) 그릴 수 없기 때문입니다. hander를 통해, 메인 스레드에게 그림 그리기를 요청 해야 합니다.

MainActivity에 1초마다 시간을 갱신하여, 보여주는 시계 예제를 통해 설명해 보겠습니다.

Usage

Handler 사용하지 않고, MainThread 접근(Exception 발생)

ClockThread를 생성하여, 1초에 한번씩 시간 값을, TextView에 set 한다면, 어떻게 될까요? Exception이 발생합니다. Main Tread에서, Process내에 존재하는 모든 View를 어떤 순서로 그릴지 알아야 하기 때문에, Main Tread 이외의 Thread는 직접 그릴 권한이 없습니다. 그렇게 때문에,Hadler를 사용하지 않고, Thread에서 직접 그림(setText)을 그린다면, exception이 발생합니다.

  • [구현] - Theread에서 1초 마다 현재 시각을 refresh 하는 코드
    public class MainActivity extends AppCompatActivity {
    
      private TextView clockTextView;
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
    
          clockTextView = findViewById(R.id.clock);
    
          class ClockThread implements Runnable {
              Calendar cal = Calendar.getInstance();
              SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
    
              @Override
              public void run() {
                  while (true) {
                      String strTime = sdf.format(cal.getTime());
                      clockTextView.setText(strTime);
    
                      try {
                          Thread.sleep(1000);
                      } catch (Exception e) {
                          e.printStackTrace();
                      }
                  }
              }
          }
    
          ClockThread clockThread = new ClockThread();
          Thread t = new Thread(clockThread);
          t.start();
      }
    }
    
  • [결과] - exception 발생

Exception 화면


Handler을 사용하여, MainThread에게 그림(setText) 그리게 위임.

Exception을 방지하기 위한 방법은 간단합니다. handler를 사용하여, 스레드에서 메인스레드에게, 메세지를 보내, 그림 그리기를 요청 하면 됩니다.

[MainActivity.java]

public class MainActivity extends AppCompatActivity {

    private TextView clockTextView;
    private Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        clockTextView = findViewById(R.id.clock);

        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                Calendar cal = Calendar.getInstance() ;

                SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
                String strTime = sdf.format(cal.getTime());

                clockTextView = findViewById(R.id.clock) ;
                clockTextView.setText(strTime) ;
            }
        } ;

        class ClockThread implements Runnable {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    handler.sendEmptyMessage(0);
                }
            }
        }

        ClockThread clockThread = new ClockThread();
        Thread t = new Thread(clockThread);
        t.start();
    }
}

Output

아래와 같이 핸들러를 사용하여,TextView에 clockTextView.setText(strTime)을 하면, exception 없이, 시간을 표시 할 수 있습니다.

[MainActivity.java]

handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        Calendar cal = Calendar.getInstance();

        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        String strTime = sdf.format(cal.getTime());

        clockTextView = findViewById(R.id.clock);
        clockTextView.setText(strTime);
    }
};

Main 화면 ___

Reference

카테고리:

업데이트: