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

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值