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

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

在通常的情况下,我们在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的Class
        Field[] fields = object.getDeclaredFields(); // 通过Class获取activity的所有字段
        for (Field field : fields) { // 遍历所有字段
            // 获取字段的注解,如果没有ViewInject注解,则返回null
            ViewInject viewInject = field.getAnnotation(ViewInject.class);
            if (viewInject != null) {
                int viewId = viewInject.value(); // 获取字段注解的参数,这就是我们传进去控件Id
                if (viewId != -1) {
                    try {
                        // 获取类中的findViewById方法,参数为int
                        Method 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,那么注解的时候可以省略

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

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

时间: 2024-10-16 18:54:21

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

Android开发学习之路--Annotation注解简化view控件之初体验

一般我们在写android Activity的时候总是会在onCreate方法中加上setContentView方法来加载layout,通过findViewById来实现控件的绑定,每次写这么多代码总觉得很烦躁.近来看了下android中有Annotation来实现这方面的简化,对于java不是很了解,就简单的看了下.上次玩web的时候,springmvc也有很多的注解,不知道怎么实现的,这里其实基本上类似. Annotation注解这里主要还是讲讲怎么使用吧,单纯的原理会把人绕进去的,没办法,

Android开发学习之路-RecyclerView滑动删除和拖动排序

Android开发学习之路-RecyclerView使用初探 Android开发学习之路-RecyclerView的Item自定义动画及DefaultItemAnimator源码分析 Android开发学习之路-下拉刷新怎么做? 本篇是接着上面三篇之后的一个对RecyclerView的介绍,这里多说两句,如果你还在使用ListView的话,可以放弃掉ListView了.RecyclerView自动帮我们缓存Item视图(ViewHolder),允许我们自定义各种动作的动画和分割线,允许我们对It

Android开发学习之路--网络编程之xml、json

一般网络数据通过http来get,post,那么其中的数据不可能杂乱无章,比如我要post一段数据,肯定是要有一定的格式,协议的.常用的就是xml和json了.在此先要搭建个简单的服务器吧,首先呢下载xampp,然后安装之类的就不再多讲了,参考http://cnbin.github.io/blog/2015/06/05/mac-an-zhuang-he-shi-yong-xampp/.安装好后,启动xampp,之后在浏览器输入localhost或者127.0.0.1就可以看到如下所示了: 这个就

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

GameService组件则是整个游戏逻辑实现的核心,而且GameService是一个可以复用的业务逻辑类. (一)定义GameService组件接口 根据前面程序对GameService组件的依赖,程序需要GameService组件包含如下方法.   ·start():初始化游戏状态,开始游戏的方法.     ·Piece[][] getPieces():返回表示游戏状态的Piece[][]数组.     ·boolean hasPieces():判断Pieces[][]数组中是否还剩Piec

Android开发学习之路-该怎么学Android(Service和Activity通信为例)

在大部分地方,比如书本或者学校和培训机构,教学Android的方式都基本类似,就是告诉先上原理方法,然后对着代码讲一下. 但是,这往往不是一个很好的方法,为什么? ① 学生要掌握这个方法的用途,只能通过记忆而不是理解 ② 当某些原理稍微复杂的时候,通过讲解是不能直接理解的,有时候下课回去了再看也不一定看得明白 ③ 对英语文档不够重视,有问题先百度 本鸟自学Android一年,慢慢也学习到了很多的方法,如果你也是一个入门不久但是觉得很多东西都不明白的新手,希望本文对你有帮助. 我觉得要想学好And

Android开发学习之路--Broadcast Receiver初体验

学习了Activity组件后,这里再学习下另一个组件Broadcast Receiver组件.这里学习下自定义的Broadcast Receiver.通过按键自己发送广播,然后自己接收广播.新建MyBroadcastReceiver,代码如下: package com.example.jared.broadcasttest; import android.content.BroadcastReceiver; import android.content.Context; import andro

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

这里选择使用android studio 集成开发环境,因为as是google推出的单独针对android开发的环境,并且迭代周期很快,因此,肯定会替代eclipse成为andorid的开发环境.对于没有eclipse基础的我来说,可以直接从as开始学习. 搭建环境, 1. 下载as withiout SDK 2. 导入自己的SDK库 3. 这里要求必须联网,而且,必须是可以FQ的,要不然速度会很慢. 4.SDK manager 如果速度比较慢,可以打开option勾选force http选项,

Android开发学习之路--图表实现(achartengine/MPAndroidChart)之初体验

??已经有一段时间没有更新博客了,在上周离开工作了4年的公司,从此不再安安稳稳地工作了.很多其它的是接受挑战和实现自身价值的提高. 离开了嵌入式linux,从此拥抱移动互联网,或许有点为时已晚.但是相信通过努力,什么时候都不会太晚.关于转行,关于这次的转型会不会成功,都是未知数,谁知道呢. 以后就好好学习互联网相关的知识.偶尔业余玩玩树莓派,玩玩机器人之类的. ??时间过得非常快,已经在新公司待了一周了,简单熟悉了环境.熟悉了产品,也学了些第三份框架的使用,什么data binding, ret

Android开发学习之路--性能优化之常用工具

??android性能优化相关的开发工具有很多很多种,这里对如下六个工具做个简单的使用介绍,主要有Android开发者选项,分析具体耗时的Trace view,布局复杂度工具Hierarchy View,应用启动时间,Memory.CPU.Network分析,静态代码检查工具Lint以及程序稳定性monkey.下面就开始学习下这些工具吧. 一.Android开发者选项 ??Andorid开发工具众多,首先就是手机自带的开发者选项了,至于手机怎么启动开发者选项,那么请自行百度或者google了,接