Android自定义工具类获取按钮并绑定事件(利用暴力反射和注解)
Android中为按钮绑定事件的有几种常见方式,你可以在布局文件中为按钮设置id,然后在MainActivity中通过findViewById方法获取按钮对象实例,再通过setOnClickListener为按钮绑定事件,如下所示:
- //1.获取控件
- btn = (Button)findViewById(R.id.button1);
- //2.绑定事件
- btn.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- callPhone();
- }
- });
你也可以在布局文件中直接为按钮设置onClick属性,然后在MainActivity中实现方法(实际应用中相较应用较少,本文主要以前一种方式为契机,故不再赘述基本语法格式)。
当一个应用中有很多按钮都需要绑定事件,甚至很多按钮需要绑定的事件具有一定的通用性的时候,我们可以参考一些流行的工具类,利用Java中的反射原理和注解,来写一个简单的工具类,帮助我们完成上述工作,让代码看起来更简洁,提高工作效率。
首先还是先简单介绍一下本文将用到的暴力反射和注解方面的一些知识吧。
反射机制,就是Java中任意一个类,可以通过获取其字节码的方式,将其属性、构造方法、方法和注解等等映射成Method、Constructor、Field、Annotation类,然后对其进行操作。所谓暴力反射是针对类中一些声明为private的成员,通过obj.setAccessible(true);的方式来强行使用私有成员。
Java中的注解Annotation,平时我们常见的一些jdk提供的注解相信大家一定不会陌生,比如@Override(提示重写父类方法,如果不能构成重写的话会报错);@Deprecated(抑制过时警告);@SuppressWarnings(抑制警告),简而言之,注解就是给JVM看的注释。本文将会用到自定义注解,大概写个小例子说明一下自定义注解的用法:
- package com.yuki.vu;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- @Target(ElementType.FIELD)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface MyInject {
- int value();
- }
@interface就是注解类的标志性声明了(注意,类成员只能是以下几种:基本数据类型、Class类型、枚举类型
元注解: |
@Retention:指定的注解作用范围 |
值: |
RetentionPolicy.SOURCE java源码范围可见 |
RetentionPolicy.CLASS .class字节码可见 |
RetentionPolicy.RUNTIME 运行的时候都可见 |
@Target:代表定义的注解修饰范围(属性,方法,类) |
ElementType.TYPE:注解修饰类 |
ElementType.METHOD:注解修饰方法 |
ElementType.FILED:注解修饰属性 |
以上只是对反射和注解的简单介绍,详细使用还请另寻资料。接下来开始编写我们的小工具,代码如下:
MyViewUtils.java文件
- package com.yuki.vu;
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- import android.app.Activity;
- import android.view.View;
- import android.view.View.OnClickListener;
- public class MyViewUtils {
- public static void inject(final Activity activity){
- //反射属性
- Field[] declaredFields = activity.getClass().getDeclaredFields();
- for (int i = 0; i < declaredFields.length; i++) {
- Field field = declaredFields[i];
- field.setAccessible(true);
- MyInject annotation = field.getAnnotation(MyInject.class);
- if (annotation!=null) {
- int id = annotation.value();
- View view = activity.findViewById(id);
- try {
- field.set(activity, view);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- //反射方法
- Method[] declaredMethods = activity.getClass().getDeclaredMethods();
- for (int i = 0; i < declaredMethods.length; i++) {
- final Method method = declaredMethods[i];
- method.setAccessible(true);
- MyClick annotation = method.getAnnotation(MyClick.class);
- if (annotation!=null) {
- int[] value = annotation.value();
- for (int j : value) {
- int id = j;
- final View btn = activity.findViewById(id);
- btn.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- try {
- method.invoke(activity, btn);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- });
- }
- }
- }
- }
- }
MyInject.java文件:
- package com.yuki.vu;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- @Target(ElementType.FIELD)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface MyInject {
- int value();
- }
MyClick.java文件:
- package com.yuki.vu;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.METHOD)
- public @interface MyClick {
- int[] value();
- }
在掌握了反射和注解用法的基础上,看懂以上代码应该不难(代码有哪里不清楚的地方可以评论留言哈^.^),你可以将这三个文件的源文件直接导入工程,也可以把它们打包成一个jar文件,日后导入libs中使用,具体使用如下:
- package com.yuki.vu;
- import android.os.Bundle;
- import android.app.Activity;
- import android.util.Log;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.TextView;
- import android.widget.Toast;
- public class MainActivity extends Activity {
- @MyInject(R.id.tv)
- private TextView tv;
- @MyInject(R.id.et)
- private EditText et;
- @MyInject(R.id.btn1)
- private Button btn1;
- @MyInject(R.id.btn2)
- private Button btn2;
- @MyInject(R.id.btn3)
- private Button btn3;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- MyViewUtils.inject(this);
- Log.d("tag", ""+btn1.getText());
- }
- @MyClick({R.id.btn1, R.id.btn2, R.id.btn3})
- public void submit(View view){
- Toast.makeText(this, ((Button)view).getText(), Toast.LENGTH_SHORT).show();
- }
- }
以上就是MainActivity的代码了。可以看到,在使用工具类的情况下,首先通过@MyInject注解获取每个带有id的按钮控件,再通过MyClick的方法为每个按钮绑定事件,最后在onCreate方法中通过一句MyViewUtils.inject(this)来完成按钮与事件的绑定,至此大功告成~撒花
其实以上内容也是从著名的工具类xUtils中参考而来,你可以在github等网站找到这些强大的工具类的源码以及详细的使用说明,故本文只为我们自己编写工具类做一个抛砖引玉的小例子,仅供参考,欢迎交流~
Android自定义工具类获取按钮并绑定事件(利用暴力反射和注解)的更多相关文章
- Android普通工具类获取Context
在普通工具类中定义一个构造方法,类成员context,用于接收传过来的context 在activity中定义: 将context传过去. 在工具类中也可以使用SharePreferences,get ...
- WzwJDBC 自定义工具类(获取连接,释放资源)
package wzwUtil;import java.io.IOException;import java.io.InputStream;import java.sql.*;import java. ...
- (转载)android 一些工具类汇总
android 一些工具类汇总 作者:曾田生z 字体:[增加 减小] 类型:转载 时间:2016-08-14我要评论 本文给大家汇总介绍了一些常用的Android工具类,非常的简单实用,有需要的小伙伴 ...
- Android 常见工具类封装
1,MD5工具类: public class MD5Util { public final static String MD5(String s) { char hexDigits[] = { '0' ...
- 53. Android常用工具类
主要介绍总结的Android开发中常用的工具类,大部分同样适用于Java.目前包括HttpUtils.DownloadManagerPro.ShellUtils.PackageUtils.Prefer ...
- 【转】Android常用工具类
主要介绍总结的Android开发中常用的工具类,大部分同样适用于Java. 目前包括HttpUtils.DownloadManagerPro.ShellUtils.PackageUtils.Prefe ...
- ThinkPHP3验证码、文件上传、缩略图、分页(自定义工具类、session和cookie)
验证码 TP框架中自带了验证码类 位置:Think/verify.class.php 在LoginController控制器中创建生存验证码的方法 login.html登陆模板中 在LoginCont ...
- 使用java的Calendar工具类获取到本月的第一天起始时间和最后一天结束时间。
1.使用java的Calendar工具类获取到本月的第一天起始时间和最后一天结束时间. package com.fline.aic.utils; import java.text.DateFormat ...
- Spring普通类/工具类获取并调用Spring service对象的方法
参考<Spring普通类获取并调用Spring service方法>,网址:https://blog.csdn.net/jiayi_0803/article/details/6892455 ...
随机推荐
- c保存lua函数
使用下面方式可保存lua任何值,目前只实现fucntion的保存,且无参数.如果需要实现参数,可自己扩展: 可实现下面方式: CFun( lua_fun ) -- okCFun( function() ...
- Android应用程序请求SurfaceFlinger服务渲染Surface的过程分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7932268 在前面一篇文章中,我们分析了And ...
- Cocos2d-X中实现菜单特效
Cocos2d-X中能够讲菜单和动作结合起来使用实现菜单特效 程序实例1:使用菜单和动作的组合实现菜单特效<一> #include "MenuItem.h" CCSce ...
- Linux shell中的一个问题 ${}带正则匹配的表达式
目前在准备龙芯项目的PMON,在研究其编译过程的时候,看到一些make 语句,百思不得其解.后来在shell编程中看到一点资料,牵扯到Shell中的正则表达式.故记录下来,以备后来查阅. 问题: 在某 ...
- 《JavaScript 闯关记》之语句
表达式在 JavaScript 中是短语,那么语句就是整句命令.表达式用来计算出一个值,语句用来执行以使某件事发生.从本质上看,语句定义了 JavaScript 中的主要语法,语句通常使用一或多个关键 ...
- css阴影--box-shadow的用法
原文:http://blog.csdn.net/freshlover/article/details/7610269 text-shadow是给文本添加阴影效果,box-shadow是给元素块添加周边 ...
- 解决net-snmp正确输出MAC地址和判断空的IP地址
function readVarbinds (buffer, varbinds) { buffer.readSequence (); while (1) { buffer.readSequence ( ...
- 初探JS-html5移动端发送指定内容短信到指定号码
原理:利用a标签跳转指定网址: sms://[号码]?body=[内容] //安卓 sms://[号码]&body=[内容] //IOS 首先简单的做两个input,一个用于输入内容,一个用于 ...
- mvc ajax请求
@{ ViewBag.Title = "ajax"; } <script src="../../Scripts/jquery-1.4.4.js" type ...
- C#操作注册表——读、写、删除、判断等基本操作
一.引入命名空间: using Microsoft.Win32; 二.创建注册表项:CreateSubKey(name)方法 添加SubKey时候首先要打开一个表项,并设置参数为true,才能成功创建 ...