Android: 使用注解findViewById
来源:互联网 发布:转行做程序员 编辑:程序博客网 时间:2024/04/29 04:56
今天模拟一个使用注解来实现findViewById的小demo, ps: 其实只能算是笔记
注解Annotation
* Java中提供,java代码中用来描述,关联任意信息和数据的一种方法(或规则)* 分类 * 按平台 * JDK自带 * @Override,表示覆写了父类方法 * @Deprecation,表示过时了 * @suppressWarning,忽视警告,suppress,镇压 * 第三方平台 * Android,@Nullable,可以为空的... * 自定义 * 按时机 * RetentionPolicy.SOURCE,只在源代码显示,变异的时候丢弃 * RetentionPolicy.CLASS,编译时会记录到字节码对象中,执行的时候丢弃 * RetentionPolicy.RUNTIME,运行的时候存在,可以通过反射获取* 注解的属性的数据类型 * 八大基本数据类型,byte,short,char,int,long,float,double,boolean * 合法类型,String,Class,Annotation,Enumeration* 注解可以使用的范围 * 接口,类:ElementType.TYPE * 方法:ElemengType.METHOD * 字段:ElementType.FIELD * 局部变量:ElementType.LOCAL_VARIABLE * 方法声明的参数:ElementType.PARAMETER * 构造方法:ElementType.CONSTRUCTOR * 包声明:ElementType.PACKAGE
思路
* 在Activity中声明View的成员变量* 给View类型的成员变量添加注解* 在onCreate方法的setContentView后运行反射解析注解的方法; * 确保在使用控件前必须获取到对象* 在inject方法中反射获取到acticity的对象,通过注解的值给activity的字段赋值
代码
* 定义一个注解类型: package com.kas.utils; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.FIELD}) //表示使用于字段 @Retention(RetentionPolicy.RUNTIME)//表示是运行时注解, public @interface ViewId { int value();//表示值是int类型 }* Activity中添加注解 public class MainActivity extends Activity { @ViewId(R.id.bt) private Button button; @ViewId(R.id.tv) private TextView tView; private int num; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); InjectUtils.inject(this); //--->必须在setContentView后调用这个方法 button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "按钮被点击了", 0).show(); tView.setText("按钮被点击了哦"); } }); } }* InjectUtils.inject(Activity activity) public class InjectUtils { public static void inject(Activity activity){//定义为静态方法,可以直接类名.调用 Class clazz = activity.getClass(); //先获取activity的字节码对象 Class mViewClass = View.class; //获取View的字节码对象,用来判断我们获取的成员变量是不是View对象 Class type = null; //定义一个Class类型的type引用,用来表示获取到的字段的类型 Field[] fields = clazz.getDeclaredFields(); //获取activity对象中的所有字段的引用 for (Field field : fields) { //遍历数组 /** * 1.设置字段为可以访问 * 如果不设置,在获取私有字段的时候,就会抛出异常 * java.lang.IllegalAccessException: access to field not allowed */ field.setAccessible(true); //设置字段为可以访问(ps,如果不设置,而该字段对象是private,就会导致抛异常) //2.获取字段的类型 type = field.getType(); //获取字段的字节码对象 /** * 3.判断该字段是否为View的子类 * 返回值为true,表示mViewClass与type表示的类和接口相同,或者mViewClass是type的父类 */ if (!mViewClass.isAssignableFrom(type)) { //判断该字段的类型是不是View或是View的子类 System.out.println(field + "不是View的子类"); continue; } /** * 判断该字段是否有注解,flag为true表示添加了注解,false表示没有添加注解 * present,提出,介绍,呈现 */ boolean flag = field.isAnnotationPresent(ViewId.class);//判断字段是否有ViewId的注解 if (!flag) { continue; } /** * 获取注解对象,如果注解对象为null,则结束本次循环 */ ViewId viewId = field.getAnnotation(ViewId.class); //获取field对应的注解对象 if (viewId == null) { continue; } /** * 获取注解表示的id */ int valueId = viewId.value(); //获取注解对象的值 try { View view = activity.findViewById(valueId); //拿到值后,调用activity中的findViewById,获取View对象 //如果findViewById查找的结果是null,说明id不存在或用户恶意攻击,直接甩出一个异常 if (view == null) { throw new IllegalStateException("there is a null result when findViewById for " + field); } field.set(activity, /*type.cast(view)*/view);//设置字段field的值, type.cast(view),表示将view强转为type类型 } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
小结
* Annotation * 定义注解: public @interface ViewId{ int value(); String desc(); } * 给注解声明值 - 注解有多个属性的时候 @ViewId(desc = "button",value = R.id.bt) private Button button; //值随便填 * 反射获取值 boolean flag = field.isAnnotationPresent(ViewId.class); ViewId viewId = field.getAnnotation(ViewId.class); int valueId = viewId.value(); //方法与定义注解的时候相互对应 String desc = viewId.desc()* Field, * boolean getAnnotationParent(Class annotation) * 判断this字段是否包含了annotation注解 * Annotation getAnnotationParent(Class annotation) * 获取制定的annotation注解对象 * int annotation.value();//获取注解对象对应的值 * Class<?> getType() * 获取this字段的字节码对象 * void setAccessible(boolean acc) * 设置为可以访问的,如果获取到的是私有的成员变量,如果不提前设置就操作的话,就会抛出异常 IllegalAccessException: access to field not allowed * 访问出错,不允许访问* Class * boolean isAssignableFrom(Class other) * 判断this是不是other类型或是other的子类 * assignable,可分配的 * T cast(Object obj), * 将obj对象强转为T,(this表示的就是T类型的一个对象)
0 0
- Android: 使用注解findViewById
- Android使用注解避免大量的findViewById()
- Android:注解初始化findViewById
- Android 注解findViewById、onClick
- Android 注解的简单使用之省去findViewById()
- Android 注解的简单使用之省去findViewById()
- 注解Butterknife使用 代替findViewById
- Android中通过注解代替findViewById方法
- Android中通过注解代替findViewById方法
- android findviewbyid的简单注解实现
- Android中通过注解代替findViewById方法
- Android中通过注解代替findViewById方法
- android通过注解实现findViewById 和 setOnClickListener
- 通过JAVA注解简化android的findViewById
- 关于android Activity中注解的使用,省去无用的findviewbyid....setonclick.....
- android 减少findViewById 的使用
- Android使用DataBinding代替findViewById
- Android中注解详解,通过注解代替findViewById方法
- 以前听师傅说, 某同学某变量没有初始化, 结果定位3-4天才解决bug
- 小程序开发过程之体验者
- 拦截器_MethodInterceptor
- 如果你想做一个网站,你只需要几小时甚至几分钟就能做出一个原型
- 笔记(6)
- Android: 使用注解findViewById
- XP下安装Ubuntu-16.04.iso
- 51、52单片机存储空间结构
- 程序设计语言的定义及一般特征
- 时间单位m和ms弄错导致系统概率异常, 耗费1天多才解决问题!
- java生成订单号的一种思路(生成友好的订单号)
- hadoop搭建前奏 --- linux下的jdk安装配置
- 【QT5.5开发】QMediaPlayerl类实现mp3音乐播放的控制台程序
- Android仿微信图片选择器