前言
今天来看看自定义注解
实例一
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitColor {
enum Color{
RED,BLUE,GREEN
}
// 方法的名称就是参数的名称,返回值类型就是参数的值类型
Color fruitColor() default Color.BLUE;
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitName {
String value() default "apple";
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitProvider {
int id() default -1;
String name() default "";
String address() default "";
}
public class Apple {
@FruitName("Orange")
private String appleName;
@FruitColor(fruitColor = FruitColor.Color.GREEN)
private String appleColor;
@FruitProvider(id=2,name="zhangsan",address = "北京")
private String appleProvider;
public void setAppleName(String appleName){
this.appleName = appleName;
}
public String getAppleName(){
return appleName;
}
public void setAppleColor(String appleColor){
this.appleColor = appleColor;
}
public String getAppleColor(){
return appleColor;
}
public void setAppleProvider(String appleProvider){
this.appleProvider = appleProvider;
}
public String getAppleProvider(){
return appleProvider;
}
}
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void click(View view) {
FruitInfoUtil.getFruitInfo(Apple.class);
}
}
运行结果
System.out: ====水果颜色GREEN
System.out: =====水果名称Orange
System.out: ===水果供应商:2--zhangsan--北京
实例二
自定义ViewMapping代替setContentView,
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ViewMapping {
int value();
}
public class ViewUtil {
// 传入的Activity
private static Class<?> activityClass;
public static void inject(Object obj) {
activityClass = obj.getClass();
injectContentView(obj);
}
private static void injectContentView(Object obj){
//判断类上是否有注解
if (activityClass.isAnnotationPresent(ViewMapping.class)) {
// 获取注解对象
ViewMapping viewMapping = activityClass.getAnnotation(ViewMapping.class);
//布局文件的id
int layoutId = viewMapping.value();
//获取方法对象,第二个参数是可变的,代表方法需要的参数类型
try {
Method setContentView = activityClass.getMethod("setContentView", int.class);
//执行方法,第一个参数是执行方法的对象,第二个是方法传入的参数的值
setContentView.invoke(obj,layoutId);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
使用
@ViewMapping(R.layout.main)
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewUtil.inject(this);
}
}
实例三
自定义注解代替fintViewById
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FindViewById {
int value();
}
private static void injectViewId(Object obj){
// 获取所有的属性,不包括继承的
Field[] fields = activityClass.getDeclaredFields();
for (Field field:fields) {
// 判断字段是否有注解
if (field.isAnnotationPresent(FindViewById.class)) {
//获取注解的值
int viewId = field.getAnnotation(FindViewById.class).value();
try {
Method findViewById = activityClass.getMethod("findViewById", int.class);
// 获取findViewById方法的返回值
Object viewValue = findViewById.invoke(obj, viewId);
if (Modifier.PUBLIC != field.getModifiers()) {
//给字段赋值前,要保证字段是可访问的
field.setAccessible(true);
}
//为字段赋值
field.set(obj,viewValue);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
实例四
自定义注解代替点击事件
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClick {
//因为可能有多个控件需要点击事件,所以这里的返回值就是一个int数组
int[] value();
}
private static void injectClickListener(Object obj){
Method[] methods = activityClass.getMethods();
for (Method method : methods) {
//如果方法上存在OnClick的注解
if (method.isAnnotationPresent(OnClick.class)) {
//获取方法上的注解
OnClick onClick = method.getAnnotation(OnClick.class);
int[] viewIds = onClick.value();
//代理处理类
MInvocationhandler invocationhandler = new MInvocationhandler(obj,method);
Object proxyInstance = Proxy.newProxyInstance(View.OnClickListener.class.getClassLoader(), new Class<?>[]{View.OnClickListener.class}, invocationhandler);
//遍历所有控件id,设置代理
for (int i : viewIds) {
try {
Object view = activityClass.getMethod("findViewById", int.class).invoke(obj, i);
if (view != null) {
Method clickListener = view.getClass().getMethod("setOnClickListener", View.OnClickListener.class);
clickListener.invoke(view,proxyInstance);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
private static class MInvocationhandler implements InvocationHandler {
private Object object;
private Method method;
public MInvocationhandler(Object object,Method method){
this.object= object;
this.method = method;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return this.method.invoke(object,args);
}
}