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

相关文章

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

Spring 框架之Springfox使用详解

《Spring框架之Springfox使用详解》Springfox是Spring框架的API文档工具,集成Swagger规范,自动生成文档并支持多语言/版本,模块化设计便于扩展,但存在版本兼容性、性... 目录核心功能工作原理模块化设计使用示例注意事项优缺点优点缺点总结适用场景建议总结Springfox 是

Spring如何使用注解@DependsOn控制Bean加载顺序

《Spring如何使用注解@DependsOn控制Bean加载顺序》:本文主要介绍Spring如何使用注解@DependsOn控制Bean加载顺序,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录1.javascript 前言2. 代码实现总结1. 前言默认情况下,Spring加载Bean的顺

如何在Mac上彻底删除Edge账户? 手动卸载Edge浏览器并清理残留文件技巧

《如何在Mac上彻底删除Edge账户?手动卸载Edge浏览器并清理残留文件技巧》Mac上的Edge账户里存了不少网站密码和个人信息,结果同事一不小心打开了,简直尴尬到爆炸,想要卸载edge浏览器并清... 如果你遇到 Microsoft Edge 浏览器运行迟缓、频繁崩溃或网页加载异常等问题,可以尝试多种方

Python的端到端测试框架SeleniumBase使用解读

《Python的端到端测试框架SeleniumBase使用解读》:本文主要介绍Python的端到端测试框架SeleniumBase使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全... 目录SeleniumBase详细介绍及用法指南什么是 SeleniumBase?SeleniumBase

Android DataBinding 与 MVVM使用详解

《AndroidDataBinding与MVVM使用详解》本文介绍AndroidDataBinding库,其通过绑定UI组件与数据源实现自动更新,支持双向绑定和逻辑运算,减少模板代码,结合MV... 目录一、DataBinding 核心概念二、配置与基础使用1. 启用 DataBinding 2. 基础布局

Android ViewBinding使用流程

《AndroidViewBinding使用流程》AndroidViewBinding是Jetpack组件,替代findViewById,提供类型安全、空安全和编译时检查,代码简洁且性能优化,相比Da... 目录一、核心概念二、ViewBinding优点三、使用流程1. 启用 ViewBinding (模块级

Spring @Scheduled注解及工作原理

《Spring@Scheduled注解及工作原理》Spring的@Scheduled注解用于标记定时任务,无需额外库,需配置@EnableScheduling,设置fixedRate、fixedDe... 目录1.@Scheduled注解定义2.配置 @Scheduled2.1 开启定时任务支持2.2 创建

mapstruct中的@Mapper注解的基本用法

《mapstruct中的@Mapper注解的基本用法》在MapStruct中,@Mapper注解是核心注解之一,用于标记一个接口或抽象类为MapStruct的映射器(Mapper),本文给大家介绍ma... 目录1. 基本用法2. 常用属性3. 高级用法4. 注意事项5. 总结6. 编译异常处理在MapSt

python编写朋克风格的天气查询程序

《python编写朋克风格的天气查询程序》这篇文章主要为大家详细介绍了一个基于Python的桌面应用程序,使用了tkinter库来创建图形用户界面并通过requests库调用Open-MeteoAPI... 目录工具介绍工具使用说明python脚本内容如何运行脚本工具介绍这个天气查询工具是一个基于 Pyt