本文主要是记录注解的使用的学习笔记,如有错误请提出。

在通常的情况下,我们在Activity中有一个View,我们要获得这个View的实例是要通过findViewById这个方法,然后这个方法返回的是一个Object类型,我们还需要进行强制的类型转换,但是相信很多人都遇到过,当我们的一个布局中有很多个控件的时候,每一个控件都要进行上面的这个操作其实是很烦躁的,特别是强制类型转换,即使是用Alt+Enter,多按几次都累了。而今天要用的是通过注解的方式来简化这一个复杂的步骤,在我们编写好相应的代码之后,获取实例的方法就变成像下面这样简单了

@ViewInject(R.id.buy)
private Button buy;

通过上面这两行简单的代码,就能把id所对应的View实例化了,下面我们一步一步的来学习如何使用注解。

先说原理,我们都要知道,在Java中,通过反射,我们可以知道每一个类的详细信息,比如有什么字段,有什么方法,类名等等,我们通过注解和反射配合,使用反射调用类中的方法,然后读取注解的参数来进行方法的执行。简单的说,就是其实我们还是会调用findViewById这个方法,但是,这个方法可以放到工具类中执行了,我们只需要像上面那样给出参数就行了。

先说下反射,反射就是允许我们动态的操作一个类,获取类的字段,执行类的方法,获取类的名字等等,在这里我们一般会用到下面的这几个方法:

getMethod:获取类中的public方法

getDeclaredMethod:获取类中的所有方法

getField:获取类中的public字段(属性)

getDeclaredField:获取类中的所有字段

还有其他的请自行参考Class类的源码

再说注解,我们看到的最多的注解获取是@Override,当我们重写父类中的方法的时候,这个注解会被编译器自动生成出来,这个注解只是表明方法是重写了父类方法。

那么我们究竟该如何自定义我们想要的注解呢?其实很简单,直接看代码:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface  ViewInject{int value();
}

@Target的意思是我们注解作用的目标,这里是ElementType.FIELD,也就是作用于字段的

 ElementType的类型有以下几种:

1.CONSTRUCTOR:用于描述构造器
 2.FIELD:用于描述字段
 3.LOCAL_VARIABLE:用于描述局部变量
 4.METHOD:用于描述方法
 5.PACKAGE:用于描述包
 6.PARAMETER:用于描述参数
 7.TYPE:用于描述类、接口(包括注解类型) 或enum声明

@Retention的意思是注解的运行级别

RetentionPolicy的类型有以下几种

1.SOURCE:在源文件中有效(即源文件保留)
 2.CLASS:在class文件中有效(即class保留)
 3.RUNTIME:在运行时有效(即运行时保留)

@interface则是表明这个类是一个注解,@号不能漏掉,否则变成了接口了

如果想对注解了解得更多,可以参考:http://www.cnblogs.com/gmq-sh/p/4798194.html 这篇博文,很详细,对于我们想要的功能,以上的内容就足够了

定义好了注解,如果我们直接来使用,是没有任何效果的,因为注解只是一段代码,并没有关联上我们的控件,所以我们要编写一个工具类来做关联

public class AnnotateUtils {public static void injectViews(Activity activity) {Class<? extends Activity> object = activity.getClass(); // 获取activity的ClassField[] fields = object.getDeclaredFields(); // 通过Class获取activity的所有字段for (Field field : fields) { // 遍历所有字段// 获取字段的注解,如果没有ViewInject注解,则返回nullViewInject viewInject = field.getAnnotation(ViewInject.class); if (viewInject != null) {int viewId = viewInject.value(); // 获取字段注解的参数,这就是我们传进去控件Idif (viewId != -1) {try {// 获取类中的findViewById方法,参数为intMethod method = object.getMethod("findViewById", int.class);// 执行该方法,返回一个Object类型的View实例Object resView = method.invoke(activity, viewId);field.setAccessible(true);// 把字段的值设置为该View的实例
                        field.set(activity, resView);} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}}}}
}

在工具类中,我们获取到了activity的Class,接着获得类中的所有字段,遍历字段,如果有ViewInject注解,则获取注解的中的值,通过获取并执行类中的方法(findViewById)来获得对应View的实例,最后把实例赋值给当前的字段,整个过程就完成了。

当我们需要使用注解的时候,我们只需要在定义View的时候,在View的字段上添加对应的注解,把Id传入,然后在onCreate方法中调用上面这个工具类的方法即可。

@ViewInject(R.id.buy)
private Button buy;
@ViewInject(R.id.money)
private TextView money;
@ViewInject(R.id.tv_power)
private TextView power;
@ViewInject(R.id.tv_life)
private TextView life;
@ViewInject(R.id.tv_dex)
private TextView dex;

@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);AnnotateUtils.injectViews(this);
}

最后,有几点说明:

①如果注解中的值不是value,那么在进行注解是时候,需要给出对应的值的名字,假如我们在注解中做了如下定义:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface  ViewInject{int id();
}

那么在注解的时候,需要这样:

@ViewInject(id = R.id.buy)
private Button buy;

因为value这个名字是默认的,如果我们定义为value,那么注解的时候可以省略

②注解还可以帮我们注入布局,设置监听等,如果有兴趣,可以继续探讨下去

③使用注解的时候,句末不能加“;”

转载于:https://www.cnblogs.com/Fndroid/p/5354644.html

Android开发学习之路-让注解帮你简化代码,彻底抛弃findViewById相关推荐

  1. android开发学习之路——连连看之游戏逻辑(五)

    GameService组件则是整个游戏逻辑实现的核心,而且GameService是一个可以复用的业务逻辑类. (一)定义GameService组件接口 根据前面程序对GameService组件的依赖, ...

  2. android开发用百度识别图片格式,Android开发学习之路-机器学习库(图像识别)、百度翻译...

    对于机器学习也不是了解的很深入,今天无意中在GitHub看到一个star的比较多的库,就用着试一试,效果也还行.比是可能比不上TensorFlow的,但是在Android上用起来比较简单,毕竟Tens ...

  3. android开发学习之路——连连看之加载图片(三)

    正如前面AbstractBoard类的代码中看到的,当程序需要创建N个Piece对象时,程序会直接调用ImageUtil的getPlayImages()方法去获取图片,该方法将会随机从res\ dra ...

  4. Android开发学习之路-环境搭建

    这里选择使用android studio 集成开发环境,因为as是google推出的单独针对android开发的环境,并且迭代周期很快,因此,肯定会替代eclipse成为andorid的开发环境.对于 ...

  5. android 程序等待时间,Android开发学习之路--性能优化之常用工具

    Android性能优化相关的开发工具有很多很多种,这里对如下六个工具做个简单的使用介绍,主要有Android开发者选项,分析具体耗时的Trace view,布局复杂度工具Hierarchy View, ...

  6. Android开发学习之路-Git的极简教程?

    Git是一个代码版本管理工具,也就是允许我们的一个项目拥有多个版本,这样我们可以随心所欲的修改我们的代码,如果出现问题,可以回退到某一个提交点.如果你还在用一堆堆注释来更新你的代码,那么可以尝试一下G ...

  7. Android开发学习之路--UI之简单聊天界面

    学了很多的ui的知识,这里就来实现个聊天的界面,首先来实现个layout的xml,代码如下: <?xml version="1.0" encoding="utf-8 ...

  8. Android图片颜色比例,Android开发学习之路-图片颜色获取器开发(1)

    系列第一篇,从简单的开始,一步一步完成这个小项目. 颜色获取就是通过分析图片中的每个像素的颜色,来分析整个图片的主调颜色,有了主调颜色,我们可以用于图片所在卡片的背景或者标题颜色,这样整体感更加强烈. ...

  9. Android开发学习之路--Camera之初体验

    顾名思义Camera就是拍照和录像的功能,像微信里面,我们想拍照传一下照片,就能够通过camera来拍照,然后存储照片.发送给好友.那么微信的app里面是不会直接通过camera api来实现的,由于 ...

最新文章

  1. ios 开发中 动态库 与静态库的区别
  2. linux下的拷贝(cp)、删除(rm)、剪切(mv)命令
  3. Android实现炫酷的星空变幻效果
  4. 浅谈Android系统开发中LOG的使用
  5. 关于c语言的基本知识,第二章_关于C语言的基本知识.ppt
  6. git 应用 resetrevert
  7. python编程入门教程下载-Python编程从入门到实践的PDF教程免费下载
  8. pip install 出现报asciii码错误的解决
  9. 追赶法源程序c语言,追赶法求三对角线方程组程序设计.doc
  10. sklearn神经网络/BP神经网络实现葡萄酒分类问题
  11. def序列化器---视图序列化反序列化
  12. 这段c语言代码牛逼在哪?看得我一脸懵逼!
  13. ROS安装与机器人环境配置总结
  14. 【Android】BLE:蓝牙低功耗基础
  15. 咸鱼硬件—Micropython快速指南
  16. 在 KubeSphere 中使用 Rook 构建云原生存储环境
  17. 洛谷P1550 打井
  18. N1小钢炮的tr设置备份
  19. _beginthreadex、CreateThread、AfxBeginThread的选择
  20. Poi 如何使用Java和POI技术生成折线图,柱状图,饼状图导出到word文档

热门文章

  1. python自学视频教程-私藏已久的7个Python视频教程
  2. 0基础学python看什么书-编程语言学python必看这三本书,少走一半弯路
  3. python基本使用-python基本用法笔记合集
  4. python手机版下载3.7.3-Python 3.7.0 来了!
  5. python基础教程书籍推荐-小猿圈推荐Python入门书籍,不知道这些你就太low了。
  6. python培训班学费-南京Python培训班学费贵吗怎么收费
  7. python读取txt文件内容-python读取压缩包里面所有*.txt文件的内容
  8. python3菜鸟教程-总算理解python3中文入门教程
  9. python中语法错误-python中的语法错误是指什么
  10. python代码怎么运行-Python程序执行原理,python程序怎么运行的?