Android手动编写ButterKnife编译时注解框架

2023-12-15 18:18

本文主要是介绍Android手动编写ButterKnife编译时注解框架,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们在项目中经常使用ButterKnife注解等框架,那里面的实现原理是什么呢?其实内部原理比较简单,今天就跟大家一起分享一下。

先上效果:

这里写图片描述

这就是我用自己写的编译时注解框架实现的效果。

MainActivity代码:

    @InjectView(R.id.btn1)Button btn1;@InjectView(R.id.btn2)Button btn2;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);InjectViewUtils.inject(this);btn1.setText("点击我111啊!!!");btn2.setText("点击我222啊!!!");}@OnClick({R.id.btn1, R.id.btn2})public void click(View view) {switch (view.getId()) {case R.id.btn1:Toast.makeText(this,"我是按钮11111",Toast.LENGTH_SHORT).show();break;case R.id.btn2:Toast.makeText(this,"我是按钮22222",Toast.LENGTH_SHORT).show();break;}}

可以看到用法都是和ButterKnife一样的。那我们就从上往下看,先看InjectView里面的代码:

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

这里面的代码很简单,主要就是一个接口和注解。解释一下注解。

@Target: @Target 用于指定该注解可以声明在哪些成员上,常见的值有FIELD和METHOD,如果不设置值得话,默认可以添加到任何元素上,但是一般不推荐这样使用。
这里的话我们设置的值是FIELD。

@Retention: 用于声明该注解生效的生命周期,有三个值可选
* 1.RetentionPolicy.SOURCE:注解之保留在源码上,编译成class的时候自动被编译器抹除
* 2.RetentionPolicy.CLASS:注解只留到字节码上,VM加载字节码时自动抹除
* 3.RetentionPolicy.RUNTIME:注解永久保留,可以被VM加载时加载到内存中
这里我们是想VM在运行时对Field上的注解进行反射,所以设置为第三个。

@interface:是声明注解类的组合关键字

然后是OnClick里面的代码:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClick {int[] value();
}

这里和刚才的都是差不多的,主要是设置@Target的值为METHOD,意思应该都是懂得。

最后是我们的重点InjectViewUtils类,代码如下:

public static void inject(final Activity activity) {Class clazz = activity.getClass();//通过字节码获取field的时候一定要用getDeclaredField(),只有该方法才能获取到任何权限修饰符的FieldField[] field = clazz.getDeclaredFields();for (int i = 0; i < field.length; i++) {Field f = field[i];//设置为可访问,暴力反射,私有也能访问f.setAccessible(true);//获取到字段的注解对象InjectView inject = f.getAnnotation(InjectView.class);if (inject == null) {continue;//如果该方法上没有注解,循环下一个}int id = inject.value();//获取注解中的值View v = activity.findViewById(id);//获取控件try {f.set(activity,v);//将控件设置给field对象} catch (IllegalAccessException e) {e.printStackTrace();}}Method[] method = clazz.getDeclaredMethods();for (int i = 0; i < method.length; i++) {final Method m = method[i];OnClick click = m.getAnnotation(OnClick.class);if (click == null) {continue;}int[] value = click.value();for (int j = 0; j < value.length; j++) {int id = value[j];final View v = activity.findViewById(id);v.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {try {m.invoke(activity,v);//反射调用用户设定的方法} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}});}}}

里面主要就是一个方法,通过反射获取字段的id,然后获取控件,然后做相应的设定,不了解反射的话,可以看下反射的知识,希望对大家有所帮助。

点击下载源码

这篇关于Android手动编写ButterKnife编译时注解框架的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/497398

相关文章

SpringBoot 获取请求参数的常用注解及用法

《SpringBoot获取请求参数的常用注解及用法》SpringBoot通过@RequestParam、@PathVariable等注解支持从HTTP请求中获取参数,涵盖查询、路径、请求体、头、C... 目录SpringBoot 提供了多种注解来方便地从 HTTP 请求中获取参数以下是主要的注解及其用法:1

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

GSON框架下将百度天气JSON数据转JavaBean

《GSON框架下将百度天气JSON数据转JavaBean》这篇文章主要为大家详细介绍了如何在GSON框架下实现将百度天气JSON数据转JavaBean,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录前言一、百度天气jsON1、请求参数2、返回参数3、属性映射二、GSON属性映射实战1、类对象映

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手

Java利用@SneakyThrows注解提升异常处理效率详解

《Java利用@SneakyThrows注解提升异常处理效率详解》这篇文章将深度剖析@SneakyThrows的原理,用法,适用场景以及隐藏的陷阱,看看它如何让Java异常处理效率飙升50%,感兴趣的... 目录前言一、检查型异常的“诅咒”:为什么Java开发者讨厌它1.1 检查型异常的痛点1.2 为什么说

基于Python编写自动化邮件发送程序(进阶版)

《基于Python编写自动化邮件发送程序(进阶版)》在数字化时代,自动化邮件发送功能已成为企业和个人提升工作效率的重要工具,本文将使用Python编写一个简单的自动化邮件发送程序,希望对大家有所帮助... 目录理解SMTP协议基础配置开发环境构建邮件发送函数核心逻辑实现完整发送流程添加附件支持功能实现htm

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

解决若依微服务框架启动报错的问题

《解决若依微服务框架启动报错的问题》Invalidboundstatement错误通常由MyBatis映射文件未正确加载或Nacos配置未读取导致,需检查XML的namespace与方法ID是否匹配,... 目录ruoyi-system模块报错报错详情nacos文件目录总结ruoyi-systnGLNYpe

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

springboot自定义注解RateLimiter限流注解技术文档详解

《springboot自定义注解RateLimiter限流注解技术文档详解》文章介绍了限流技术的概念、作用及实现方式,通过SpringAOP拦截方法、缓存存储计数器,结合注解、枚举、异常类等核心组件,... 目录什么是限流系统架构核心组件详解1. 限流注解 (@RateLimiter)2. 限流类型枚举 (