System.out.println("Hello, World");

1. 콜백 메서드 정의하기 

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

사용자와 상호 작용하는 주체가 뷰이므로 이벤트 콜백은 주로 뷰가 제공한다. 



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

- 이벤트 리스너는 통상 특정 뷰에 대해 정의되는 것이므로 외부에 선언할 필요 없이 액티비티 클래스 내부에 이너클래스로 선언한다. 

액티비티는 리스너 타입의 객체 TouchListener를 멤버로 선언 및 생성하고 뷰는 setOnTouchListener 메서드로 리스너 객체를 터치 이벤트와 연결했다.



리스너로 이벤트를 처리하는 절차를 간략하게 요약하면 다음과 같다.

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

 2) 리스너 객체 TouchListener를 선언 및 생성한다.

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



3. 액비티비가 리스너 구현

- 안드로이드 프로젝트에는 최소한 액티비티 하나는 존재하므로 액티비티가 리스너 인터페이스를 구현하는 것도 물론 가능하다. 액비티비는 Activity 클래스를 이미 상속 받지만 인터페이스는 개수에 상관없이 얼마든지 더 상속받을 수 있다. 선언문에서 인터페이스를 상속받고 본체에 핸들러 메서드를 정의하면 된다. But 이렇게 만들어진 뷰는 액티비티에 강하게 종속된다는 면에서 기동성이 떨어진다. 이 뷰를 다른 액티비티에 재사용하려면 액티비티가 구현하는 리스너를 분리하여 다른 액티비로 옮겨야 한다. 뷰와 관련도니 메서드가 뷰 자신에게 포함되지 않고 부모가 구현해 주기 때문에 독립성이 떨어진다.


4. 뷰가 리스너 구현

 - 액티비티가 리스너를 구현 할 수 있다면 뷰도 마찬가지이다. 액티비비나 뷰나 둘 다 클래스이므로 임의의 인터페이스를 구현할 수 있다. 어떤 이유로든 뷰를 파생했다면 클래스 선언문이 있으므로 액티비티한테 빌붙을 필요 없이 뷰 스스로가 자신이 필요로 하는 리스너 인터페이스를 상속받아 구현하면 된다.


5. 익명 이너 클래스 사용

- 3, 4번은 간편하기는 하지만 인터페이스를 구현해 줄 적당한 클래스가 있을 때만 쓸수 있는 방법이므로 역시 일반적인 해법은 아니다. 

자바 이벤트 처리 방식의 특성상 하나당 객체 하나씩을 만들어야 하는데 이는 너무 번거로운 일이다. 이벤트 처리를 위해 꼭 필요한 알맹이는 사실 핸들러 메서드 뿐이다. 그러나 객체 지향 언어이다보니 메서드가 홀로 존재할 수 없으며 클래스 안에 넣어야 하고 객체를 생성한 후 등록하는 번거러운 과정을 거쳐야 한다. 

자바는 이런 경우를 위해 언어 차원에서 익명 이너 클래스라는 문법을 제공한다. 상위 클래스나 인터페이스의 메서드 하나를 재정의하기 위해 클래스를 선언하는 경우, 그리고 그 클래스의 객체가 단 하나만 필요한 경우는 굳이 클래스를 선언할 필요 없이 상속과 재정의를 동시에 할 수 있다.



6. 익명 이너 클래스의 임시 객체 사용

 - 익명클래스의 객체 TouchListener는 두 개를 생성할 수 없으며 오로지 하나만 생성할 수 있다. 특정 뷰에 대한 이벤트 핸들러로만 쓸 경우는 굳이 두 개를 생성할 필요도 없다. 

이럴때는 객체의 이름조차도 줄 필요가 없으며 임시 객체를 하나를 생성하여 등록 메서드의 인수로 전달해버리면 된다.



또한 핸들러의 우선순위는 

뷰의 리스터 -> 뷰의 onTouchEvent 콜백 메서드 -> 액티비티의 onTouchEvent 콜백 메서드로 보면 된다. 보다시피 좁은 범위일수록 우선 순위가 높은데 이는 상식과 일치한다. 그러나 이 우선순위가 절대적인것은 아니다. 각 핸들러는 리턴값으로 다음 순위 메서드의 호출 기회를 통제한다.


Posted by 김마농