您的位置:首页 > 编程语言

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

2016-07-08 23:42 330 查看
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的形式解决
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: