Android 基于反射实现简易版ButterKnife

文章目录

  • Android 基于反射实现简易版ButterKnife
    • 定义注解
    • 定义绑定类解析注解
    • 使用
    • 代码下载

Android 基于反射实现简易版ButterKnife

反射比较消耗资源,一般不推荐使用。

定义注解

/*** 用于绑定元素*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface BindView {@IdRes int value();
}
/*** 定义元注解*/
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventType {Class methodClass(); //方法所在的ClassString methodName(); //方法名
}
/*** 绑定点击事件*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@EventType(methodClass = View.OnClickListener.class, methodName = "setOnClickListener")
public @interface OnClick {@IdRes int[] value() default {};
}
/*** 绑定长按事件*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@EventType(methodClass = View.OnLongClickListener.class, methodName = "setOnLongClickListener")
public @interface OnLongClick {@IdRes int[] value() default {};
}

定义绑定类解析注解

public class MyButterKnife {public static void bind(Activity activity) {//获取类中所有变量Field[] fields = activity.getClass().getDeclaredFields();//获取类中所有方法Method[] methods = activity.getClass().getDeclaredMethods();bindFields(activity, fields);bindMethods(activity, methods);}/*** 绑定变量** @param activity* @param fields*/private static void bindFields(Activity activity, Field[] fields) {for (Field field : fields) {//判断是否被@BindView注解if (field.isAnnotationPresent(BindView.class)) {//获取@BindView注解BindView bindView = field.getAnnotation(BindView.class);if (bindView != null) {//设置访问权限if (!field.isAccessible()) {field.setAccessible(true);}//获取注解值int id = bindView.value();//获取ViewView view = activity.findViewById(id);try {//通过反射设置值field.set(activity, view);} catch (IllegalAccessException e) {e.printStackTrace();}}}}}/*** 绑定方法** @param activity* @param methods*/private static void bindMethods(Activity activity, Method[] methods) {for (Method method : methods) {//判断是否被@OnClick或@OnLongClick注解if (method.isAnnotationPresent(OnClick.class) || method.isAnnotationPresent(OnLongClick.class)) {//获取方法上的所有注解Annotation[] annotations = method.getAnnotations();//遍历注解for (Annotation annotation : annotations) {//获取注解的注解类型Class<? extends Annotation> annotationType = annotation.annotationType();//判断注解是否为@EventTypeif (annotationType.isAnnotationPresent(EventType.class)) {//获取EventType注解EventType eventType = annotationType.getAnnotation(EventType.class);assert eventType != null;//获取方法的ClassClass methodClass = eventType.methodClass();//获取方法名String methodName = eventType.methodName();//设置访问权限method.setAccessible(true);try {//获取OnClick或OnLongClick的value值Method valueMethod = annotationType.getDeclaredMethod("value");//获取绑定的idint[] viewIds = (int[]) valueMethod.invoke(annotation);//代理对象Object proxy = Proxy.newProxyInstance(methodClass.getClassLoader(),new Class[]{methodClass},new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method m, Object[] args) throws Throwable {return method.invoke(activity, args);}});assert viewIds != null;//遍历id并绑定事件for (int id : viewIds) {//获取Activity的ViewView view = activity.findViewById(id);//获取指定方法,如setOnClickListener方法,参数类型是OnClickListenerMethod clickMethod = view.getClass().getMethod(methodName, methodClass);//执行方法clickMethod.invoke(view, proxy);}} catch (Exception e) {e.printStackTrace();}}}}}}
}

使用

public class MainActivity extends AppCompatActivity {@BindView(R.id.textView)TextView textView;@BindView(R.id.imageView)ImageView imageView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);MyButterKnife.bind(this);textView.setText("hello");imageView.setImageResource(R.mipmap.ic_launcher);}@OnClick({R.id.btn1, R.id.btn2})public void click(View view) {switch (view.getId()) {case R.id.btn1:Toast.makeText(this, "btn1 click", Toast.LENGTH_SHORT).show();break;case R.id.btn2:Toast.makeText(this, "btn2 click", Toast.LENGTH_SHORT).show();break;}}@OnLongClick({R.id.btn1, R.id.btn2})public boolean longClick(View view) {switch (view.getId()) {case R.id.btn1:Toast.makeText(this, "btn1 longClick", Toast.LENGTH_SHORT).show();break;case R.id.btn2:Toast.makeText(this, "btn2 longClick", Toast.LENGTH_SHORT).show();break;}return true;}
}

代码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/57789.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM核心原理解读(一)---执行引擎

Java虚拟机规范制定了Java字节码执行引擎的概念模型,Java执行引擎作用概括起来就是执行编译产生的Java class文件,为用户提供了底层OS的调用,屏蔽了不同平台硬件和OS的差异性,使得编写的代码无差别的在各个平台运行;对于Java字节码执行一般有解释执行和编译执行两种,具体使用哪…

Git git fetch 和 git pull 区别

git pull和git fetch的作用都是用于从远程仓库获取最新代码&#xff0c;但它们之间有一些区别。 git pull会自动执行两个操作&#xff1a;git fetch和git merge。它从远程仓库获取最新代码&#xff0c;并将其合并到当前分支中。 示例&#xff1a;运行git pull origin master会从…

学乐多光屏P90:智能引领儿童学习新时代

随着科技的迅猛发展&#xff0c;儿童教育正逐渐迈入数字化时代。在这个变革的浪潮中&#xff0c;学乐多光屏P90以其卓越的功能和深刻的教育理念&#xff0c;成为了智能儿童学习领域的引领者&#xff0c;为孩子们开启了全新的学习体验。 融合创新技术&#xff0c;引领学习变革 …

GD32-舵机的原理

GD32-舵机的原理 舵机的现一脉宽与舵机转动角度 旋转编码器的原理 顺时针&#xff1a;A的下降沿时&#xff0c;B处于高电平&#xff1b; 逆时针&#xff1a;A的下降沿时&#xff0c;B处于低电平&#xff1b; #ifndef _ENCODER_DRIVE_H #define _ENCODER_DRIVE_H#include &quo…

2023高教社杯数学建模思路 - 复盘:校园消费行为分析

文章目录 0 赛题思路1 赛题背景2 分析目标3 数据说明4 数据预处理5 数据分析5.1 食堂就餐行为分析5.2 学生消费行为分析 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 赛题背景 校园一卡通是集…

JavaScript—对象与构造方法

目录 json对象&#xff08;字面值&#xff09; js中对象是什么&#xff1f; 如何使用&#xff1f; 关联数组 js对象和C#对象有什么区别&#xff1f; 构造函数 什么是构造方法&#xff1f; 如何使用构造方法&#xff1f; 如何添加成员&#xff1f; 对象的动态成员 正则…

Python|爬虫和测试|selenium框架的安装和初步使用(一)

前言&#xff1a; Python作为一门胶水语言来说&#xff0c;可以说是十分的优秀&#xff0c;什么事情都可以干&#xff0c;并且在某些领域还能干的非常不错&#xff0c;尤其是在爬虫和测试领域&#xff0c;该语言可以说是没有对手。 这么说的原因是因为如果你要使用爬虫爬取某…

汽车自适应巡航系统车距控制策略研究

1 引言 自适应巡航控制( Adaptive Cruise Control&#xff0c;ACC) 是汽车驾驶辅助系统的重要组成部分&#xff0c;其作用是根据车距传感器探测到本车( ACC 车辆) 与主目标车辆( 前车) 之间的相对位置和相对速度信息&#xff0c;自动调节ACC 车辆的节气门开度或部分制动力矩( 即…

c++ 通讯录管理系统 黑马教程 (02)

个人笔记&#xff0c;这个是自己写的&#xff0c;未观看黑马教程&#xff0c;所以差异会比较大。 #include "iostream" #include<conio.h> using namespace std; /*** 通讯录管理系统* 功能* 1.添加联系人* 2.显示联系人* 3.删除联系人* …

Oracle的lag、lead函数使用

Oracle的lag、lead函数使用 一、LAG函数&#xff08;当前行之前&#xff09;二、LEAD函数&#xff08;当前行之后&#xff09; Oracle数据库中的LAG和LEAD函数可以用于查询行与前/后行之间的差异。 一、LAG函数&#xff08;当前行之前&#xff09; LAG函数返回分析窗口内的当前…

微信小程序社区户口管理的系统设计与实现

摘要 我国的户口管理制度由来已久&#xff0c;我国对于合法居民在新生儿的出生、户口的落地、迁移以及户口的注销上都有着详细的管理条例进行约束。通过户口的管理可以更好地对我国的居民人数进行有效的内容统计&#xff0c;在进行人口普查的过程中也能够实现更好的、更加精准的…

探索数据湖中的巨兽:Apache Hive分布式SQL计算平台浅度剖析!

文章目录 ◆ Apache Hive 概述1.1 分布式SQL计算1.2 Hive的优势 ◆ 模拟实现Hive功能2.1 元数据管理2.2 解析器2.3 基础架构2.4 Hive架构 ◆ Hive基础架构3.1 Hive架构图3.2 Hive组件3.2.1 元数据存储3.2.2 Driver驱动程序3.2.3 用户接口 ◆ Hive部署4.1 VMware虚拟机部署步骤一…

【学习笔记】求解线性方程组的G-S迭代法

求解线性方程组的G-S迭代法 // 运行不成功啊function [x,k,index] Gau_Seid(A,b,ep,it_max) % 求解线性方程组的G-S迭代法&#xff0c;其中 % A为方程组的系数矩阵 % b为方程组的右端项 % ep为精度要求&#xff0c;省缺为1e-5 % it_max为最大迭代次数&#xff0c;省缺为100 % …

新KG视点 | Jeff Pan、陈矫彦等——大语言模型与知识图谱的机遇与挑战

OpenKG 大模型专辑 导读 知识图谱和大型语言模型都是用来表示和处理知识的手段。大模型补足了理解语言的能力&#xff0c;知识图谱则丰富了表示知识的方式&#xff0c;两者的深度结合必将为人工智能提供更为全面、可靠、可控的知识处理方法。在这一背景下&#xff0c;OpenKG组织…

Docker运维篇

Docker运维篇 Docker 设置自启Docker 指定容器设置自启重启linux 计算机网络常见错误汇总centos 7 Docker容器启动报WARNING: IPv4 forwarding is disabled. Networking will not work Docker 设置自启 # 重启docker sudo systemctl enable docker# 设置开机自启 systemctl e…

eslint

什么是eslint ESLint 是一个根据方案识别并报告 ECMAScript/JavaScript 代码问题的工具&#xff0c;其目的是使代码风格更加一致并避免错误。 安装eslint npm init eslint/config执行后会有很多选项&#xff0c;按照自己的需求去选择就好&#xff0c;运行成功后会生成 .esli…

bpmnjs Properties-panel拓展(属性设置篇)

最近有思考工作流相关的事情&#xff0c;绘制bpmn图的工具认可度比较高的就是bpmn.js了&#xff0c;是一个基于node.js的流程图绘制框架。初始的框架只实现了基本的可视化&#xff0c;想在xml进行客制化操作的话需要拓展&#xff0c;简单记录下几个需求的实现过程。 修改基础 …

【数据分析】缺失值处理

1. 均值填充&#xff1a;对于数值型的特征&#xff0c;采用该特征在已有数据中的平均值或中位数来填充缺失值。 2. 众数填充&#xff1a;对于类别型的特征&#xff0c;采用该特征在已有数据中出现频率最高的类别来填充缺失值。 3. 插值法&#xff1a;通过已有的数据&#xff0c…

每天一道leetcode:542. 01 矩阵(图论中等广度优先遍历)

今日份题目&#xff1a; 给定一个由 0 和 1 组成的矩阵 mat &#xff0c;请输出一个大小相同的矩阵&#xff0c;其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。 两个相邻元素间的距离为 1 。 示例1 输入&#xff1a;mat [[0,0,0],[0,1,0],[0,0,0]] 输出&#xff…

java八股文面试[多线程]——指令重排序

关于a的操作&#xff0c;由原来的6个指令&#xff0c;变成了4个指令。 1. 指令重排序的介绍 1&#xff09;指令重排序的类型 在执行程序时为了提高性能&#xff0c;编译器和处理器常常会对指令做重排序。 重排序分三种类型&#xff1a;编译器优化的重排序 编译器在不改变单线…