美文网首页
从Xutils运行时注解复习Java注解

从Xutils运行时注解复习Java注解

作者: Lilee丶 | 来源:发表于2018-09-23 11:39 被阅读0次
    • 最近在做复习整理,顺便把整理的一些东西记录下来。

    • Annotation(注解)是JDK1.5及以后版本引入的。它可以用于创建文档,跟踪代码中的依赖性,甚至执基本编译时检查。几乎所有的框架设计中都会用到注解类。

    • 先看一下一个注解类的格式

        @Target(ElementType.METHOD)
        @Retention(RetentionPolicy.RUNTIME)
        public @interface NoodlesClick {
            int value() default 1;
        }
      
      • Target 表示这个注解可以放在那里使用,ElementType枚举常用有 PACKAGE、TYPE、METHOD、FIELD 几种,分别表示可以用在 包,类,方法,和成员变量上面。我们最常见的注解@Override就是用在方法上的。
      • Retention 表示这个注解可以保留到什么时候。RetentionPolicy枚举有SOURCE、CLASS、RUNTIME分别表示,在保留在源.java文件,javac后的.class文件,和保留到程序运行时。这篇写的就是要保存在运行时的。
      • 注解的声明用@interface声明。

    先创建注解类##

    今天只实现View的绑定和点击事件。

    • 先创建两个注解类

            //需要导入的包
            import java.lang.annotation.ElementType;
            import java.lang.annotation.Retention;
            import java.lang.annotation.RetentionPolicy;
            import java.lang.annotation.Target;
      
    • 这个是点击的注解类NoodlesClick 只能用在方法上。

            @Target(ElementType.METHOD)
            @Retention(RetentionPolicy.RUNTIME)
            public @interface NoodlesClick {
                int value() default 1;
            }
    
    • 这个是View绑定的注解类NoodlesInject 只能用在成员变量上。

            @Retention(RetentionPolicy.RUNTIME)
            @Target(ElementType.FIELD)
            public @interface NoodlesInject {
                int value() default 1;
            }
      
    • 下面是常规的布局文件 和MainActivity的创建

      • 布局文件,只有一个TextView和Button

      • 这是MainActivity的代码

          public class MainActivity extends Activity {
          
              /**
               * 这里引用注解 @NoodlesInject
               * 后面括号里面的value 为 刚才注解里面的方法的返回值,方法默认值为1;
               *  int value() default 1;
               *  这里将TextView的id传进去。
               */
              @NoodlesInject(value = R.id.tv)
              TextView mTv;
          
              @Override
              protected void onCreate(Bundle savedInstanceState) {
                  super.onCreate(savedInstanceState);
                  setContentView(R.layout.activity_main);
                  /**
                   * 这里是重点。将当前对象传进去,进行View的绑定以及事件的绑定
                   */
                  NoodlesUtil.inject(this);
              }
              
              /**
               * 这里引用注解 @NoodlesClick
               * 后面括号里面的value 为 刚才注解里面的方法的返回值,方法默认值为1;
               *  int value() default 1;
               *  这里将Button的id传进去。
               */
              @NoodlesClick(value = R.id.btn)
              private void onClick(View v) {
                  Toast.makeText(this, mTv.getText().toString().trim(), Toast.LENGTH_SHORT).show();
              }
          }
        
      • NoodlesUtil是用来做具体的注解与Activity的操作的。

          public class NoodlesUtil {
        
              /**
               * 
               * DESC : 静态方法,用于给activity层调用 . <br/> 
               * @param activity  要解析此activity中的成员变量和方法。
               */
              public static void inject(Activity activity) {
                  bindView(activity);
                  bindClick(activity);
              }
              
              /**
               * 
               * DESC : 解析成员变量 . <br/> 
               * @param activity
               */
              private static void bindClick(Activity activity) {
                  try {
                      //获取activity的class。
                      Class<? extends Activity> clazz = activity.getClass();
                      //利用反射  获取activity中的所有成员变量
                      Field[] fields = clazz.getDeclaredFields();
                      //遍历成员变量
                      for (Field field : fields) {
                          /**
                           * getAnnotation 方法为获取成员变量field上是否有NoodlesInject注解。
                           *     @NoodlesInject(value = R.id.tv)
                           *     TextView mTv;
                           * 这是Activity中写的成员变量,如果返回不为null,则表明上面有此注解
                           */
                          NoodlesInject annotation = field.getAnnotation(NoodlesInject.class);
                          if (annotation != null) {
                              //调用注解中的方法,value 获取到值  R.id.tv
                              int id = annotation.value();
                              //通过id找View,将本来需要在activity中写的代码放在了这里来。
                              View view = activity.findViewById(id);
                              field.setAccessible(true);
                              //将找到的View赋值给 textView  类似于  TextView mTv = (TextView)view;
                              field.set(activity, view);
                          }
                      }
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
          
              }
              
              /**
               * 
               * DESC : 解析绑定了点击事件的注解类 . <br/> 
               * @param activity
               */
              private static void bindView(final Activity activity) {
                  try {
                      //获取activity的class。
                      Class<? extends Activity> clazz = activity.getClass();
                      //利用反射  获取activity中的所有的方法
                      Method[] methods = clazz.getDeclaredMethods();
                      //遍历方法
                      for (final Method method : methods) {
                          /**
                           * getAnnotation 方法为获取方法method上是否有NoodlesClick注解。
                           *   @NoodlesClick(value = R.id.btn)
                           *   private void onClick(View v) { ... }
                           * 这是Activity中写的方法,如果返回不为null,则表明上面有此注解
                           */
                          NoodlesClick annotation = method.getAnnotation(NoodlesClick.class);
                          if (annotation != null) {
                              //调用注解中的方法,value 获取到值  R.id.btn
                              int id = annotation.value();
                              //通过id找View。
                              final View view = activity.findViewById(id);
                              //设置view的点击事件。
                              view.setOnClickListener(new OnClickListener() {
                                  
                                  @Override
                                  public void onClick(View v) {
                                      try {
                                          method.setAccessible(true);
                                          //将View传入method方法,并执行method方法 
                                          // --》 就是执行Activity中的onclick方法。
                                          method.invoke(activity, view);
                                      } catch (Exception e) {
                                          e.printStackTrace();
                                      }
                                  }
                              });
                          }
                      }
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          }
        

    具体的执行,已经在代码的注释中,这个demo中除了布局文件之外的代码已经全部贴在这里了,运行时注意导包。
    xutils3.0 和butterknife 现在已经全部将运行时改为编译时了,至于编译时的原理,后面会整理出来。

    相关文章

      网友评论

          本文标题:从Xutils运行时注解复习Java注解

          本文链接:https://www.haomeiwen.com/subject/qmwfoftx.html