본문 바로가기

6. With IT/6.1 Android

Android-Event3

이벤트 핸들러(Event Handler)


이벤트 처리

이벤트(Event)라는것을 사용자의 입력이나 시스템 상황 변화에 따라 발생하는것!
안드로이드에서는 이벤트를 처리하는 다양한 방법이 존재한다.
각 방법별로 특성이 조금씩 다르고 여러가지 변형된 구조를 허락한다.

처리방법은 크게 콜백메서드 Override리스너 구현이라는 2가지 방법이 있다.
그리고 리스너를 구현하는 방법은 5가지 정도로 세분화 된다.



1. 콜백 메서드 재정의

콜백(Callback) : 특정 이벤트가 발생했을때 시스템에 의해 자동으로 호출되는 메서드

이벤트를 처리하는 가장 쉬운 방법으로 해당 클래스를 재정의해서 콜백 메서드를 작성하는것이다.
사용자가 화면을 터치할 때, 키를 누르거나 뗄 때, 트랙볼을 굴릴 때 호출되는 콜백 메서드들을 재정의 하는 경우가있다.
이벤트가 발생하게 되면 해당 정보가 인수로 전달되는데,
키를 누른 경우 누른 키의 정보, 터치 했을경우 터치한 곳의 자표 등이 전달된다.
콜백을 재정의 하게 되면 이런 이벤트의 정보와 시점을 얻을 수 있다.

<단점>
- 작성의 번거로움
메서드를 재정의 하기 위해서는 반드시 superClass를 상속 받아야 하는데 Button이나 Textview같은 위젯의 경우 매번
myButton같은 클래스를 만들어야 하는 번거로움이 있다.
- 콜백 종류의 부족
모든 이벤트에 대한 콜백이 정의되어 있는것은 아니다.
터치, 키입력 외에도 여러 이벤트가 있지만, 모든것을 콜백으로 처리 할 수 있는것은 아니다.

import android.app.Activity;
import android.content,*;
import android.os.Bundle;
import android.View.*;
import android.widget.*;

pulbic class Handler extends Activity{
    pulic void onCreate(Bundle saveInstanstanceState){
        super.onCreate(saveInstanceState);
        View wv = new MyView(this);
        setContentView(vw);
    }
    
    protected class MyVieew extends View{
        public MyVieew(Context context){
            super(context);
        }

        public boolean onTouchEvent(MotionEnvet event){
            super.onTouchEvnet(event); //supert의 메서드를 호출하여 부모에게 처리기회를 먼저 제공한다.
            if(event.getAction() == MotionEvnet.ACTION_DOWN){
                   Toast.makeText(Handler.this, "Touch Evnet Receive", Toast.LENGTH_SHORT).show();
                    return true;
            }
            return false;
        }
    }
    
}


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

2.1 별도 클래스 생성

리스너(Listener)는 특정 이벤트를 처리하는 인터페이스이다.
리스너에는 대응되는 이벤트를 받는 단 하나의 메서드가 선언되어 있으며,
메서드들은 View클래스의 inner클래스 인터페이스로 선언되어있다.
메서드들은 구현이 되어있지 않은 추상메서드이다.

리스너로 이벤트를 처리하는 절차
1) 리스너를 구현하는 클래스를 선언하고, 추상메서드를 구현한다.
2) 리스너 객체를 선언 및 생성한다.
3) 준비된 리스너 객체를 뷰의 이벤트와 연결한다.

단점
번거롭다.
처리해야하는 이벤트가 늘어날 때 마다 클래스를 생성해야하는 일이 생길 수 있다.

public class HandleEvent extends Activity{
    public void onCreate(Bundle saveInstanceState){
        super.onCreate(saveInstanceStae);
        View v = new View(this);    
        v.setOnTouchListener(TouchListener);    // 3. 리스너 등록
        setContentView(v);
    }
    
    // 1. 리스너 구현 클래스 선언
    class TouchListenerClass implements View.onTouchListener{
        public boolean onTouch(View v, MotionEvent event){
            if(event.getAction() == MotionEvnet.ACTION_DOWN){
                Toast.makeText(HandleEvent.this, "Touch Event Received", Toast.LENGTH_SHORT).show();
                retuurn ture;
            }
            return false;
        }
    }
    
    // 2. 리스터 객체 생성
    TouchListenerClass TouchListener = new TouchListenerClass();
}


2.1 Activity가 리스너를 구현

인터페이스는 누가 구현할 것인가 대해서는 아무 제약이 없다.
때문에 기존에 존재하는 클래스에 구현해도 좋다.
안드로이드에서는 최소한 하나의 Activity는 존해하기때문에 그 Activity에 리스너를 구현하는것도 가능하다.
implements View.OnTouchListener로 인터페이스를 받고 클래스 내부에 메서드를 오버라이드한다.
그리고 setOnTouchListener(this)를 사용해서 연결해준다.

   단점
   Activity라는 큰 단위가 하위의 뷰를 위한 메서드를 제공한다는 점에서 집중도가 떨어지고 결합성이 증가하게된다.
이런식으로 만들어진 뷰는 Activity에 종속적이다.
즉, 뷰가 다른 Activity에 재 사용되려면 리스너를 다른 Activity로 옮겨야된다.

public class HandleEvent extends Activity implements View.OnTouchListener{
    public void onCreated(Bundle saveIndstanceStae){
        super.onCreate(saveInstanceStae);
        View v = new View(this);
        v.setOnTouchListener(this);
        setContentView(v);
    }

    public boolean onTouch(View v, MotionEvnet evnet){
        if(event.getActivity() == MotionEvnet.ACTION_DOWN){
            Toast.makeText(this, "Touch Evnet Receive", Toast.LENGTH_SHORT).show();
            return true;
        }
        return false;
    }
}


2.3 뷰가 리스너를 구현
    위와 같은 애용이지만, Activity가 아닌 View가 인터페이스를 구현한다.
구조상 깔끔하고 뷰를 재 활용하기도 편리하다.

단점
리스너 구현만을 위해 일부러 뷰에 상속을 받는것은 번거로울 수도있다.
앞선 방법도 마찬가지 이지만, 인터페이스를 구현해줄 적당한 클래스가 있을 때만 사용할 수 있다.


public class HandleEvnet extends Activity{
    public void onCreated(Bundle saveIndstanceStae){
        super.onCreate(saveInstanceStae);
        View v = new View(this);
        v.setOnTouchListener(this);
        setContentView(v);
    }

    protected class MyView extends View implements View.onTouchListener{
        public MyView(Context context){
            super(context);
        }
        public boolean onTouch(View v, MotionEvnet event){
           if (event.getAction() == MotionEvent.ACTION_DOWN) {

                    Toast.makeText(HandleEvent.this,"Touch Event Received",

                     Toast.LENGTH_SHORT).show();

                     return true;

               }

               return false;

        }
        
    }
}


2.4 익명 이너 클래스 이용
3,4번의 방법은 간편하지만 인터페이스를 구현해 줄 적당한 클래스가 있을 때만 쓸수있는 방법이다.
원론적으로는 2번처럼 클래스를 하나 만들어서 구현하는것이 가장 완벽하다.
2번의 단점은 리스너 하나를 위해 클래스를 일일이 선언하기 번거롭다는 점이엇다.
단 하나의 메서드를 위해서 하나의 클래스를 만들어야 하는 것이다.

우리가 필요한 것은 메서드라는 알맹이 뿐인데 여러중의 코딩을 더해서 클래스를 만들어야한다는 것은 비효율적인 일이다.
때문에 자바에서는 익명 이너 클래스라는 문법을 제공한다.
익명 이너 클래스는 상위 클래스나 인터페이스에서 메서드 하나를 재정의 하기 위해서 클래스를 선언해야 하는 경우 상속과 재정의를 동시에 할 수 있는 방법이다.

public class HandleEvent extends Activity {

           public void onCreate(Bundle savedInstanceState) {

                     super.onCreate(savedInstanceState);

                     View vw = new View(this);

                     vw.setOnTouchListener(TouchListener);

                     setContentView(vw);

           }

//아래의 코드에서 코드가 쓰여진 것을 봐서는 TouchListener View.OnTouchListener의 인스턴스로 보일 수 있지만 인터페이스는 객체를 생성할 수가 없다. 이는 인터페이스를 상속받아 메서드를 구현하는 이름 없는 서브 클래스 타입의 객체이다.

 

           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;

                     }

           };

}



2.5 익명 이너 클래스의 임시 객체 사용
onCreate에 포함되는 v.setOnTouchListener(TouchListener)코드와 아래의 익명 클래스를 합쳐놓은 형태이다.
이경우가 가장 함축적인 방법으로 많은 곳에서 이런 방법을 사용한다.
사실 좀 복잡해 보일 수도 있는 코드지만, 이런 형식을 많이 쓰니 알아두도록 하자.

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);

           }

'6. With IT > 6.1 Android' 카테고리의 다른 글

Android-Lifecycle  (0) 2011.05.27
Android-Runtime  (0) 2011.05.27
Android-Event2  (0) 2011.05.27
Android-Event  (0) 2011.05.27
안드로이드란??플랫폼/프레임워크란?  (0) 2011.01.19