RoboGuice와 더불어 안드로이드 코딩을 굉장히 심플하게 만들어주는 AndroidAnnotations(AA) 오픈소스 라이브러리는 @Click 이라는 아주 유용한 어노테이션을 제공합니다.
뷰의 ID가 설정된 어노테이션을 메소드에 선언해주면 설정된 뷰에 click 이벤트가 발생할 때 해당 메소드가 실행됩니다.
기존에는 view.setOnClickListener(new OnClickListener() { ...}) 와 같은 OnClickListener 익명 클래스로 도배된 지저분한 코딩이 필요했었죠.
@Click(R.id.myButton)
void myButtonClicked() {
... ... // R.id.myButton을 누르면 이 메소드가 호출됩니다.
}
@Click
void anotherButton(View clickedView) {
... ... // R.id.anotherButton 버튼을 누르면 이 메소드가 호출됩니다.
}
@Click({R.id.myButton1, R.id.myButton2})
void myButtonsClicked() {
... ... // R.id.myButton1 또는 R.id.myButton2를 누르면 이 메소드가 호출됩니다.
}
AA를 사용하지 않는(사용하기 싫은?) 환경을 위해 비슷한 기능을 제공하는 우리만의 @Click을 만들어 보겠습니다.
먼저 Click 어노테이션을 작성합니다. value는 클릭 이벤트가 발생하는 뷰의 id 값입니다.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Click {
int[] value() default -1;
}
@Click 어노테이션을 선언하는 메소드는 아래의 제약사항을 준수해야 합니다(AA의 @Click도 마찬가지입니다).
- 리턴 타입은 void만 가능
- 파라미터는 없거나 View 타입의 1개만 가능
- Exception을 던지는 것이 가능하지만 메소드 caller한테는 throw되지 않음 (AA에서는 아예 checked Exception도 못던집니다).
그리고 공통 액티비티 클래스에서 android.app.Activity의 onContentChanged() 메소드를 오버라이딩합니다.
/**
* 어노테이션에 설정된 뷰에 대해 클릭 이벤트 발생시 해당 메소드가 실행되도록 리스너 등록.
*
*/
@Override
protected void onContentChanged() {
super.onContentChanged();
processClick(this);
}
public static void processClick(final Activity activity) {
Class clazz = activity.getClass();
for (final Method m : clazz.getDeclaredMethods()) {
Click click = m.getAnnotation(Click.class);//m.isAnnotationPresent(Click.class)
if (click == null)
continue;
Class<?>[] params = m.getParameterTypes();
final boolean hasViewParameter = (params.length > 0);
int[] ids = click.value();
for (int id : ids) {
View view = activity.findViewById(id);
if (view != null) {
view.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
try {
if (hasViewParameter) {
m.invoke(activity, view);
} else {
m.invoke(activity);
}
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
});
}
}
}
}
다 됐습니다. 공통 액티비티를 상속받은 액티비티에서 AA의 그것과 동일한 기능을 수행하는 @Click 어노테이션을 사용할 수 있습니다. 간단하죠?
※ 단, AndroidAnnotations의 @Click과 차이점이 몇가지 있습니다.
- AA에서는 setContentView()에 @Click 처리코드가 작성되지만, 위에서는 onContentChanged()에서 @Click을 처리하도록 했습니다.
- AA의 @Click은 뷰의 id가 주어지지 않은 경우 메소드 이름으로 뷰 id를 자동으로 찾지만 위 코드는 그러한 기능은 제공하지 않습니다.
- AA에서는 컴파일타임에 Java Annotation Processing에 의해 @Click 처리 코드가 생성되지만 위 코드는 런타임에 @Click이 붙은 메소드를 이벤트리스너를 등록합니다.
'Android' 카테고리의 다른 글
안드로이드 쓰레드 사용 총정리 (0) | 2013.04.15 |
---|---|
AndroidAnnotations의 @Background, @UiThread 어노테이션 흉내내기 (0) | 2012.11.07 |
[RoboGuice] injection 이후 특정 메소드 실행 방법 (0) | 2012.04.29 |
[RoboGuice] 어노테이션 활용 (0) | 2012.04.29 |
RoboGuice에서 Aspect에 injection하는 방법 (0) | 2012.04.29 |