ButterKnife的使用极大方便了Android程序员的开发,实际上,我们可以自己模仿一下实现。

首先就是要了解Java注解的使用。

我们首先要声明一个@interface,也就是注解类:

@Target(ElementType.FIELD)//表示用在字段s上
@Retention(RetentionPolicy.RUNTIME)//表示在生命周期是运行时
public @interface ViewBinder {int id() default -1;String method() default "";String type() default "";
}

@interface是用于自定义注解的,它里面定义的方法的声明不能有参数,也不能抛出异常,并且方法的返回值被限制为简单类型、String、Class、emnus、@interface,和这些类型的数组。

注解@Target也是用来修饰注解的元注解,它有一个属性ElementType也是枚举类型,值为:ANNOTATION_TYPE,CONSTRUCTOR ,FIELD,LOCAL_VARIABLE,METHOD,PACKAGE,PARAMETER和TYPE,如@Target(ElementType.METHOD) 修饰的注解表示该注解只能用来修饰在方法上。

@RetentionRetention注解表示需要在什么级别保存该注释信息,用于描述注解的生命周期,它有一个RetentionPolicy类型的value,是一个枚举类型,它有以下的几个值:

1.用@Retention(RetentionPolicy.SOURCE)修饰的注解,指定注解只保留在源文件当中,编译成类文件后就把注解去掉;
     2.用@Retention(RetentionPolicy.CLASS)修饰的注解,指定注解只保留在源文件和编译后的class 文件中,当jvm加载类时就把注解去掉;
     3.用@Retention(RetentionPolicy.RUNTIME )修饰的注解,指定注解可以保留在jvm中,这样就可以使用反射获取信息了。

默认是RUNTIME,这样我们才能在运行的时候通过反射获取并做对应的逻辑处理。

接下来我们就是利用反射来获取注解的属性以及做相应的处理:

public class ViewBinderParser implements Parsable {private ViewBinderParser() {}public static void inject(Object object) {ViewBinderParser parser = new ViewBinderParser();try {parser.parse(object);} catch (Exception e) {LogUtil.e(e.toString());}}@Overridepublic void parse(final Object object) throws Exception {View view = null;final Class<?> clazz = object.getClass();Field[] fields = clazz.getDeclaredFields();//获得Activity中声明的字段for (Field field : fields) {// 查看这个字段是否有我们自定义的注解类标志的if (field.isAnnotationPresent(ViewBinder.class)) {ViewBinder inject = field.getAnnotation(ViewBinder.class);int id = inject.id();if (id < 0) {throw new Exception("id must not be null");}if (id > 0) {field.setAccessible(true);if (object instanceof View) {view = ((View) object).findViewById(id);} else if (object instanceof Activity) {view = ((Activity) object).findViewById(id);}field.set(object, view);//给我们要找的字段设置值String methodName = inject.method();if (!methodName.equals("")) {OnEventListener listener = new OnEventListener(object);String type = inject.type();if (type.equals("")) {throw new Exception("Please input the type of Method,such as 'method=OnClick'");}if (type.equals("OnClick")) {listener.setOnClick(id, methodName);}}}}}}
}

我们通过inject将添加注解的对象传进来,然后进入注解属性的解析方法中。

利用反射获取所有声明的字段,然后再利用isAnnotationPresent方法查看该字段是否有添加的注解类型,再从该字段中获取注解,通过定义好的方法获取到相应的属性值。我们这里获取到对应的View的id,然后在这里进行View的初始化,以及事件的绑定。

完成事件的绑定还需要一个类:

public class OnEventListener {private Object object;public OnEventListener(Object object) {this.object = object;}public void setOnClick(int id, final String methodName) {View view = null;if (object instanceof View) {view = ((View) object).findViewById(id);} else if (object instanceof Activity) {view = ((Activity) object).findViewById(id);}view.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {MethodModel methodModel = new MethodModel();Class clazz = methodModel.getClass();try {Method method = clazz.getMethod(methodName, new Class[]{});method.invoke(methodModel, new Object[]{});} catch (NoSuchMethodException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}});}
}

目前只是实现了点击事件的绑定。

接着我们就可以这样使用我们自定义的注解了:  

public class MainActivity extends ActionBarActivity {@ViewBinder(id = R.id.cet_receiver)protected CustomEditText cetReceiver;@ViewBinder(id = R.id.cet_cc)protected CustomEditText cetCC;@ViewBinder(id = R.id.cet_content)protected CustomEditText cetContent;@ViewBinder(id = R.id.cet_subject)protected CustomEditText cetSubject;@ViewBinder(id = R.id.iv_receiver)protected ImageView ivReceiver;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ViewBinderParser.inject(this);ivReceiver.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {cetCC.setVisibility(View.VISIBLE);}});}
}

注解的使用可以让我们的代码更加简洁,但前提是,这种前提是否有必要。

转载于:https://www.cnblogs.com/wenjiang/p/4298143.html

Android注解编程的第一步---模仿ButterKnife的ViewBinder机制相关推荐

  1. 编程的第一步都要使能时钟吗_在您的第一份编程工作中要做的11件事

    编程的第一步都要使能时钟吗 Firsts are exciting but can also be overwhelming. When I started my first programming ...

  2. 《UNIX网络编程》第一步:编写自己的daytime客户端,并从daytime服务器获取时间

    编写自己的daytime客户端,并从daytime服务器获取时间 @Author:CSU张扬 @Email:csuzhangyang@gmail.com or csuzhangyang@qq.com ...

  3. 计算机系的同学应该有更高的雄心壮志!学编程只是第一步!

    前些天有个计算机系的同学和我聊天,想在暑假做个人网站,博客之类的系统,我劝他说计算机系的学生(其实不止是计算机系,可以扩展到所有热爱编程的在校同学)应该有更高的雄心壮志,去挑战更有难度的东西. 为什么 ...

  4. python编程基础是什么-编程学习第一步,让你20天搞定Python编程

    大家好,欢迎大家阅读篇文章,Python是当前火爆的编程语言之一:从后台开发到自动化,从数据分析到人工智能,都有Python的身影.我们掌握Python,就有了进入这些行业的可能.下面简单介绍下老猫和 ...

  5. python计算器基础知识_Python基础(一):将Python当做计算器、编程的第一步

    我们来尝试一些简单的 Python 命令.启动解释器然后等待主提示符 >>> 出现(不需要很久).1.1. 数字 解释器表现得就像一个简单的计算器:可以向其录入一些表达式,它会给出返 ...

  6. python可以自学编程吗-编程学习第一步,让你20天搞定Python编程

    大家好,欢迎大家阅读篇文章,Python是当前火爆的编程语言之一:从后台开发到自动化,从数据分析到人工智能,都有Python的身影.我们掌握Python,就有了进入这些行业的可能.下面简单介绍下老猫和 ...

  7. android unity3d开发学习第一步

    1:下载unitysetup 开发环境 http://unity3d.com/unity/download/download-windows 2:下载三维制作软件 制作我们需要的场景 http://u ...

  8. Android网络编程入门解析

    网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者可能觉得网络编 ...

  9. Java、Android注解代码生成(ButterKnife原理、ViewBinding)

    前言 首先需要一些先验知识: 浅谈Java/Android下的注解 Java.Android基础之-反射 Java.Android静态代理与动态代理 简介 在我们常用的框架中注解和自动生成代码的身影很 ...

  10. Hello Android – 迈出android开发第一步

    环境搭建基本上比较顺利,除了下载SDK需要花不少时间 L 比起.Net的开发环境,java总是需要DEV更多的自己动手,偶更喜欢傻瓜型的部署 J 构建HelloAndroid项目: 1. File - ...

最新文章

  1. 2022 美国国家工程院院士公布:张宏江等入选海外院士,马斯克及微软CEO在列...
  2. master-slave(主/从)模式
  3. socket简单通信
  4. 从无到有算法养成篇-链式存储结构之循环链表
  5. numpy 数组抽取_Python 关于NumPy的用法介绍
  6. HubSpot company数据在UI上的展示和通过API方式进行获取
  7. js 对已知数组数据的导出EXCEL
  8. c# sizeof_C#程序演示sizeof()运算符的示例
  9. 通过BizTalk WCF适配器实现异构数据库/系统间的数据同步
  10. 浮点类型float double 以及BigDecimal
  11. 骁龙855加持!OPPO Reno正面照揭晓:边框窄得吓人
  12. JWT(JSON Web Token)的基本原理
  13. 《编程能力基础》刷题笔记(41 题)
  14. 台达b3伺服参数设置方法_台达伺服驱动器参数设置一览表
  15. Swift:快速上手攻略
  16. Alink(1):Alink概述
  17. android数据格式化,手机格式化了?教你找回安卓手机误删数据
  18. 在idea中启动tomcat项目报错提示“java.util.zip.ZipException: error in opening zip file“
  19. 学生Dreamweaver静态网页设计 基于HTML+CSS+JavaScript制作简食餐厅美食网站制作
  20. 虚拟化:gva、gpa、hva、hpa转化

热门文章

  1. 自定义AlertDialog
  2. rails rake和示例
  3. (转)Low-Mid-High
  4. C++中#和##的特殊使用
  5. error: expected constructor, destructor, or typ...
  6. Net设计模式实例之桥接模式( Bridge Pattern)(4)
  7. 蓝桥杯dfs搜索专题
  8. (转载)python re模块详解 正则表达式
  9. YBT 2.4 AC自动机
  10. RestTemplate 发送 get 请求使用误区 多值为null