自定义注解

前言

今天来看看自定义注解

实例一

@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);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值