콜백 메서드 - 해당되는 글 1건
크리에이티브 커먼즈 라이선스
Creative Commons License

이벤트 처리?

미리 정의된 절차대로 동작하는 것이 아니라 사용자의 입력이나 시스템의 상황 변화에 따라 발생하는 이벤트에 적절히 반응하도록 작성해야 한다. 이벤트를 처리에는 6가지 방법이 제공된다.

 

[이벤트1: 콜백 메서드 재정의]

이벤트를 받는 가장 쉬운 방법은 해당 클래스를 재정의해 콜백 메서드를 작성하는 것이다. 콜백은 특정 이벤트가 발생했을 때 시스템에 의해 자동으로 호출되는 메서드이며 이 메서드에 코드를 작성해 놓으면 이벤트 발생시의 동작을 정의할 수 있다. 사용자와 상호 작용하는 주체가 뷰이므로 이벤트 발생시의 동작을 정의할 수 있다.

ð  콜백은 특정이벤트 발생시 시스템에 의해 자동으로 호출되는 메서드이다.

ð  이 메서드에 코드를 작성해 놓으면 이벤트 발생시 동작을 정의할 수 있다.

 

대표적인 콜백 메서드

  boolean onTouchEvent (MotionEvent event) //사용자가 화면을 터치할 때

  boolean onKeyDown (int keyCode, KeyEvent event) //키를 누를 때

  boolean onKeyUp (int keyCode, KeyEvent event) //키를 뗄 때

  boolean onTrackballEvent (MotionEvent event) //트랙볼을 굴릴 때

 콜백 메서드를 재정의하면 특정 이벤트가 발생하는 시점을 정확하게 가로챌 수 있을 뿐 아니라, 이벤트에 대한 상세정보까지 얻을 수 있다.

특정사건에 대해 특정 메서드를 호출하기로 프레임워크와 약속되어 있으므로, 지정된 원형대로 메서드를 재정의만 하면 된다. 그러나 이 방법에는 몇 가지 단점 및 한계가 있다.

1)     메서드를 재정의 하기 위해서는 반드시 슈퍼 클래스를 상속받아야 한다.

View onTouchEvent 메서드를 수정할 수 없으므로, View객체를 상속받은 새로운 클래스를 파생시켜야만 원하는 코드를 집어 넣을 수 있다.

뷰를 재정의하는 것은 문제가 되지 않지만 Button이나 TextView같은 위젯의 경우 이벤트를 처리하기 위해 일일이 클래스를 만들어야 하는 번거로움이 있다.

2)     프레임워크는 일반적인 이벤트에 대해 콜백 메서드를 제공하지만, 모든 이벤트에 대해 콜백이 다 정의되어 있는 것은 아니다. 터치나 키 입력외에도 진동센서, 조도센서 등 별별 이벤트가 많이 있는데 이것을 일일이 지정할 수는 없기 때문이다. 또한 이벤트는 사용자가 정의할 수도 있으므로, 콜백 메서드는 이벤트를 처리하는 일반적인 방법이 될 수 없다.

 

[이벤트2:  리스너 인터페이스 구현]

 

대표적인 리스너에 선언된 메서드

  View.OnTouchListener : boolean onTouch (View v, MotionEvent event)

  View.OnKeyListener : boolean onKey (View v, int keyCode, KeyEvent event)

  View.OnClickListener : void onClick (View v)

  View.OnLongClickListener : boolean onLongClick (View v)

  View.OnFocusChangeListener : void onFocusChange (View v, boolean hasFocus)

 

  View 클래스의 내부 인터페이스로 OnTouchListener 인터페이스가 선언되있고, 이 인터페이스는 onTouch라는 추상 메서드를 포함한다이 메서드를 이벤트 핸들러라고 부른다. 다른 리스너들도 이름만 조금 다를 뿐, 거의 비슷한 구조이다그러나 인터페이스는 어디까지나 껍데기일뿐, 그 자체가 이벤트를 받을 수는 없다단순히 특정 이벤트를 처리하는 핸들러의 원형이 어떠해야 한다는 것을 강제할 뿐이다.

 

  이벤트를 처리 하는 방법은

  (1) 리스너를 구현하는 클래스를 선언하고 그 객체를 생성한다.

       클래스가 되려면 리스너의 추상 메서드인 핸들러를 구체적으로 구현해야 한다.

  (2) 이렇게 구현된 객체를 리스너 객체라고 한다.

  (3) 리스너를 구현한 다음에는 뷰에 이벤트가 발생했을 때, 핸들러가 호출되도록 연결해야 한다.

       구현만 한다고 이벤트와 리스너가 자동으로 연결되는 것은 아니므로, 어떤 리스너가 어떤

    이벤트를 처리하는지 등록해야 한다.

등록 메서드는 리스너별로 따로 준비되어 있는데, 이름이 "set+리스너"식이어서 외우기 쉽다.

 

  void setOnTouchListener (View.OnTouchListener)

  void setOnKeyListener (View.OnKeyListener)

  void setOnClickListener (View.OnClickListener)

  void setOnLongClickListener (View.OnLongClickListener)

  void setOnFocusChangeListener (View.OnFocusChangeListener)

 

리스너로 이벤트 처리하는 절차

리스너를 구현하는 클래스를 선언하고 추상 메서드를 구현한다.

리스너 touchListener를 선언 및 생성한다.

준비된 리스너 객체를 뷰의 이벤트와 연결한다.

 

콜백 메서드는 상속을 받아야만 재정의 할 수 있는데, 리스너는 인터페이스이므로 임의의 클래스가 구현할 수 있다. 그러나 인터페이스 구현을 위해 별도의 클래스를 하나 더 선언해야 한다는 번거로움이 있다.

 

[이벤트3: 액티비티가 리스너 구현]

기존의 클래스에 인터페이스를 구현하는 방법

클래스를 따로 선언하지 않고 액티비티가 인터페이스를 직접 구현하는 방식이다.

But. 액티비티랄는 큰 단위가 하위의 뷰를 위한 메서드를 제공한다는 면에서 불합리하다.

 

[이벤트4: 뷰가 리스너 구현]

액티비티가 리스너를 구현할 수 있는 것처럼 뷰도 마찬가지이다.

액티비티나 뷰, 둘다 클래스이므로 임의의 인터페이스를 구현할 수 있다.

이벤트를 처리하는 메서드를 내부에 포함한다는 면에서 구조상 깔끔하고 뷰를 재활용하기도 유리하다. But. 리스너 구현만을 위해 일부러 상속을 받는다는 것이 번거롭다.

 

[이벤트5: 익명 이너 클래스를 사용]

이벤트 처리를 위해 꼭 필요한 알맹이는 사실 핸들러 메서드뿐이다.

그런데 이 코드를 핸들러로 감싸기 위해 더 많은 코드가 필요하다.

자바는 이런 경우를 위해 익명 이너 클래스라는 문법을 제공한다.

1)     상위 클래스나 인터페이스의 메서드 하나를 재정의하기 위해 클래스를 선언하는 경우

2)     그리고 그 클래스의 객체가 단 하나만 필요한 경우

굳이 클래스를 선언할 필요 없이 상속과 재정의를 동시에 할 수 있다.

 

[이벤트6: 익명 이너 클래스의 임시 객체 사용]

가장 함축된 형태의 이벤트 처리 코드

안드로이드에서 주로 이 방법을 통해 이벤트 핸들러를 작성한다.

5번 방법은 익명의 이너 클래스를 사용함으로서 코드가 대폭 짧아졋는데 사실 이럴때는 객체의 이름조차도 줄 필요가 없으며, 임시 객체 하나를 생성하여 등록 메서드의 인수로 전달해 버리면 된다. 객체 생성문 자체를 아예 setOnTouchListener 호출문 안에 넣어 버리는 것이다.

 

[정리]

이벤트를 처리하는 방법은

크게 상속받은 후 콜백 메서드를 재정의하는 방법과 리스너를 등록하는 방법 두 가지로 분류할 수 있고 리스너를 액티비티에 구현하느냐, 뷰에 구현하느냐, 주체에 따라 몇가지 형태로 나누어 지고 코드를 압축하는 방법이 달라진다.

 

[이벤트5를 사용한 코드]

public class HandleEvent extends Activity {
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      View vw = new View(this);
      vw.setOnTouchListener(TouchListener);
      setContentView(vw);
    }

    private View.OnTouchListener TouchListener = new View.OnTouchListener() { // 상속과 재정의를 동시에
      public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
          Toast.makeText(HandleEvent.this,"Touch Event Received",
          Toast.LENGTH_SHORT).show();
          return true;
        }
        return false;
      }
    };
  }

 

[이벤트6을 사용한 코드]

public class HandleEvent extends Activity {
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      View vw = new View(this);
      vw.setOnTouchListener(new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
          if (event.getAction() == MotionEvent.ACTION_DOWN) {
            Toast.makeText(HandleEvent.this,"Touch Event Received",
            Toast.LENGTH_SHORT).show();
            return true;
          }
          return false;
        }
      });
      setContentView(vw);
    }
  }

저작자 표시
신고

'Study > Android' 카테고리의 다른 글

[Android: Media Scanner]  (0) 2011.03.23
[Android: 다국어 지원]  (0) 2011.03.23
[Android: 위젯의 클릭 이벤트]  (0) 2011.03.21
[Android: 이벤트 핸들러]  (0) 2010.10.16
[Android: 출력]  (0) 2010.10.15
[Android: 레이아웃(Layout)?]  (0) 2010.10.03
Trackback 0 | Comment 0

강군v's Blog is powered by Daum & tistory

 

티스토리 툴바