注解编程-简单的反射实现

来源:互联网 发布:windows bat 相对路径 编辑:程序博客网 时间:2024/06/08 00:58

http://www.importnew.com/10294.html
http://blog.csdn.net/lmj623565791/article/details/43452969
http://my.oschina.net/ososchina/blog/345288
给类网站

Java5.0版本引入注解,成为Java平台比较只要的一部分,@Override等常见的注解,
为什么要引入注解
开发 Android findviewByid 要写很多遍,为了将xml里面和代码进行配置, 这些步骤都是可以省略的 通过ButterKnif xutils等

简单的注解编程 开始

//Target 表上该注解用在什么地方,ElementType是可能的类型 有类和成员变量等@Target(ElementType.TYPE)//表示需要在什么级别保存该注解信息,设置为运行时@Retention(RetentionPolicy.RUNTIME)public @interface ContentView {    int value();}@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface ViewInject {    int value();}

@Target? –注解用于什么地方后面跟着的是需要注解的类型
@Target – 表示该注解用于什么地方。如果不明确指出,该注解可以放在任何地方。以下是一些可用的参数。需要说明的是:属性的注解是兼容的,如果你想给7个属性都添加注解,仅仅排除一个属性,那么你需要在定义target包含所有的属性。

ElementType.TYPE:用于描述类、接口或enum声明
ElementType.FIELD:用于描述实例变量
ElementType.METHOD
ElementType.PARAMETER
ElementType.CONSTRUCTOR
ElementType.LOCAL_VARIABLE
ElementType.ANNOTATION_TYPE 另一个注释
ElementType.PACKAGE 用于记录java文件的package信息
Retention 什么时候需要注解

RetentionPolicy.SOURCE – 在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override, @SuppressWarnings都属于这类注解。

RetentionPolicy.CLASS – 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。

RetentionPolicy.RUNTIME– 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。

@ContentView(value = R.layout.activity_main)public class MainActivity extends AppCompatActivity {    @ViewInject(R.id.iv)    private ImageView imageView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        ViewInjectUtils.inject(this);    }

在代码中申明了两个注解简单理解注解对于哪个位置-》Tager-》你需要注解哪个类 如ViewInject我需要处理ElementType.FIELD 就对应一个对象,字段 就ImageView, 内部的value[] 这对应 你彻底进来如R.id.iv注解已经写好了 这个时候需要注入到布局中

    private static final String METHOD_SET_CONTENTVIEW = "setContentView";    private static final String METHOD_FIND_VIEW_BY_ID = "findViewById";  public static void injectContentView(Activity activity) {        Class<? extends Activity> clazz = activity.getClass();//        查找该类上是否有ConteView.class的注解        ContentView contentView = clazz.getAnnotation(ContentView.class);        if (contentView != null) {            int layoutId = contentView.value();            try {//                类查找方法                Method method = clazz.getMethod(METHOD_SET_CONTENTVIEW, int.class);//               将成员变量设置为public                method.setAccessible(true);                method.invoke(activity, layoutId);            } catch (Exception e) {                e.printStackTrace();            }        }    }    public static void injectViews(Activity activity) {        Class<? extends Activity> clazz = activity.getClass();        Field[] fields = clazz.getDeclaredFields();        for (Field f : fields) {            ViewInject viewInject = f.getAnnotation(ViewInject.class);            if (viewInject != null) {                int value = viewInject.value();                if (value != -1) {                    // 初始化View                    try {                        Method method = clazz.getMethod(METHOD_FIND_VIEW_BY_ID, int.class);                        Object resView = method.invoke(activity, value);                        f.setAccessible(true);                        f.set(activity, resView);                    } catch (Exception e) {                        e.printStackTrace();                    }                }            }        }    }

通过搜索Class搜索Annotation()->调用方法》获取彻底进来的id 反射实现
在第二篇http://blog.csdn.net/lmj623565791/article/details/43452969 洪阳博客中对于onClick 事件的处理 使用了动态代理处理,不具体介绍
为什么会涉及到动态代理, 如果view.setOnclickLinstener(this),对于this这个是接口我们无法获取具体的实现类,无法对接口进行方法处理, 通过Proxy.newxxx的形式解决

0 0