非常讨厌android事件绑定和findViewById()代码太繁琐。今天在阅读代码的时候看见,网上有类似的控件。可是我又不想下。于是乎就随手写了个。平时写个Demo用还行。用于项目可能会有bug。毕竟只是我简单的封装。后续可能会优化
@OnClick 和 @Bind 和 核心代码处理类。这些使用者不需要关心。下面会有使用方法。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OnClick {
int value();
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Bind {
int value();
}
import android.app.Activity;
import android.util.Log;
import android.view.View;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class EventUtils {
private static String TAG = "EventUtils";
private static Map<Integer, View> bindMap = new HashMap<>();
public static void bind(Activity activity) {
try {
final Class<? extends Activity> aClass = activity.getClass();
initBindField(activity, aClass, activity);
Method[] methods = aClass.getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(OnClick.class)) {
if (!method.getGenericReturnType().equals(Void.TYPE)) {
Log.e(TAG, "The return value class must be void");
return;
}
int value = method.getAnnotation(OnClick.class).value();
if (bindMap.containsKey(value)) {
View view = bindMap.get(value);
bindOnClickEvent(activity, method, view);
} else {
View view = activity.findViewById(value);
bindOnClickEvent(activity, method, view);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static void bindOnClickEvent(final Activity instance, final Method method, View view) {
if (!method.isAccessible()) {
method.setAccessible(true);
}
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes != null && parameterTypes.length > 0 && parameterTypes[0].equals(View.class)) {
invoke(method, instance, v);
} else {
invoke(method, instance);
}
}
});
}
private static void initBindField(Activity activity, Class<? extends Activity> aClass, Activity instance) throws IllegalAccessException {
for (Field field : aClass.getDeclaredFields()) {
if (field.isAnnotationPresent(Bind.class)) {
int value = field.getAnnotation(Bind.class).value();
if (View.class.isAssignableFrom(field.getType())) {
if (!field.isAccessible()) {
field.setAccessible(true);
}
View view = activity.findViewById(value);
field.set(instance, view);
bindMap.put(value, view);
}
}
}
}
private static Object invoke(Method method, Object instance, Object... args) {
if (!method.isAccessible()) {
method.setAccessible(true);
}
try {
return method.invoke(instance, args);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
使用方法:
@Bind(R.id.result)
private TextView textView;
@OnClick(R.id.clearBtn)
public void click(View v) {}
//View参数可选。
//@Bind @OnClick 可以任意使用其中一个,也可以同时使用。
//下面是最重要的一步。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注意:初始化下绑定
EventUtils.bind(this);
}