posted by By훈트 2010.08.16 20:03

Android 는 Event를 처리하는 방법이 6가지가 있다.

1. 콜백 메소드 정의

해당 클래스를 재정의해 콜백 메소드를 작성하는 것이다.
대표적인 콜백 메소드는 아래와 같다.
boolean onTouchEvent(MotionEvent event)
boolean onKeyDown(int keyCode, KeyEvent event)
...

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

public class HandlerEvent extends Activity {
  ...

  protected class MyViiew extends View {
    ...

   public boolean onTouchEvent(MotionEvent event) {
     super.onTouchEvent(event);
     if(event.getAction() == MotionEvent.ACTION_DOWN) {
       ...
     }
   }
  }
}

위 코드는 MyView를 터치했을때 발생하는 이벤트를 콜백함수를 통해 처리는 코드이다.

콜백 메소드를 재정의 하는 방법은 아주 간단하고 직관적이다. 특정사건에 대해 특정메소드를 호출하기로 프레임워크와 약속되어 있으므로 지정된 원형대로 메소드를 재정의 하면 된다. 
그러나 여기에는 몇가지 단점 및 한계가 있다.
(1) 메소드를 재정의 하기 위해서는 반드시 슈퍼클래스를 상속받아야 한다. 그리고 Button이나 TextView같은 위젯의 경우 이벤트를 처리하기 위해 MyButton, MyTextView 와 같은 클래스를 만들어야 하는 번거로움이 있다.
(2) 프레임워크는 자주 발생하는 일반적인 이벤트에 대해서는 콜백 메소드를 제공하지만 모든 이벤트에 대한 콜백이 정의되어 있는것은 아니다. 그러므로 콜백메소드는 일반적인 방법이 될 수 없다.


2. 리스너 인터페이스 구현

리스너(listener)는 특정 이벤트를 처리하는 interface이다. 이벤트 발생 여부를 기다리고 있는 객체라고 할 수 있다.
하지만 interface이기 때문에 우리가 직접 구현을 해주어야 한다.

대표적인 listerner는 아래와 같다.
View.OnTouchListener : boolean onTouch (View v, MotionEvent event)
View.OnKeyListener:boolean onKey (View v, int keyCode, KeyEvent event)
...

이벤트를 처리하려면 listener를 구현하는 클래스를 선언하고 그 객체를 만들어야 한다. 
그 다음 뷰에 이벤트가 발생했을때 구현된 listener가 호출되도록 연결해야 한다. set+listener이름 으로 정의되는 등록메소드를 이용하여 연결하면 된다.
void setOnTouchListener(View.OnTouchListener I)
void setOnKeyListener(View.OnKeyListener I)
...

아래는 리스너 클래스를 구현한 코드이다.

 public class CustomView extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View vw = new View(this);
        vw.setOnTouchListener(touchListener);
        setContentView(vw);
    }
    
    TouchListenerClass touchListener = new TouchListenerClass();
     
    class TouchListenerClass implements View.OnTouchListener {
        public boolean onTouch(View v, MotionEvent event) {
          // TODO Auto-generated method stub
          if(event.getAction() == MotionEvent.ACTION_DOWN) {
            return true;
          }
          return false;
        } 
    }
}


3. Activity가 listener 구현

Activity가 직접 listener interface를 구현하는 방식이다.

아래는 구현한 코드이다.

 public class CustomView extends Activity implements View.OnTouchListener {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View vw = new View(this);
        vw.setOnTouchListener(this);
        setContentView(vw);
    }

    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub
        if(event.getAction() == MotionEvent.ACTION_DOWN) {
           return true;
        }
        return false;
    }
}


이렇게 만들어진 view는 activity에 강하게 종속되게 된다. 


4. View가 listener 구현

View 스스로가 자신이 필요로 하는 listener interface를 상속받아 구현하는 방식이다.

아래는 구현된 코드이다.

 public class CustomView extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MyView vw = new MyView(this);
        vw.setOnTouchListener(vw);
        setContentView(vw);
    }
    
    protected class MyView extends View implements View.OnTouchListener {
       public MyView(Context context) {
          super(context);
          // TODO Auto-generated constructor stub
       }
     
       public void onDraw(Canvas canvas) {
           Paint pnt = new Paint();
           pnt.setColor(Color.BLUE);
           canvas.drawColor(Color.WHITE);
           canvas.drawCircle(100, 100, 80, pnt);
       }

       public boolean onTouch(View v, MotionEvent event) {
           // TODO Auto-generated method stub
           return false;
       }
    }
}


자신에게 발생되는 이벤트를 자기 스스로 처리하는 방식이다. 이벤트를 처리하는 메소드를 내부에 포함한다는 면에서 구조상 깔끔하고 view를 재활용하기도 유리하다.


5. 익명 inner Class 사용

2번 listener interface를 구현하는 방식과 거의동일하나 문법적인 차이가 좀 있다.

아래는 구현 코드이다.
 public class CustomView extends Activity {
    /** Called when the activity is first created. */
    @Override
    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) {
           // TODO Auto-generated method stub
           return false;
       }
    }; // 생성과 정의를 동시에 할 수 있다.

}

위 방식은 구현한 listener 클래스를 재활용하기 힘들다는 점이다. 익명 inner class의 특성상 클래스의 이름이 없기 때문이다.


6. 익명 inner class의 임시 객체 사용

이름이 좀 복잡하다. 객체 생성문을 vw.setOnTouchListener 호출문안에 넣어버리는 방식이다.
역시 문법상의 차이이다.

아래는 구현 코드이다.

 public class CustomView extends Activity {
    /** Called when the activity is first created. */
    @Override
    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) {
                  // TODO Auto-generated method stub
                  return false;
               }
            }
        );
        setContentView(vw);
    }
}



신고