Android 基于反射实现简易版ButterKnife

这篇具有很好参考价值的文章主要介绍了Android 基于反射实现简易版ButterKnife。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Android 基于反射实现简易版ButterKnife

反射比较消耗资源,一般不推荐使用。文章来源地址https://www.toymoban.com/news/detail-689265.html

定义注解

/**
 * 用于绑定元素
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface BindView {
    @IdRes int value();
}
/**
 * 定义元注解
 */
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventType {
    Class methodClass(); //方法所在的Class

    String 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();
                    //获取View
                    View 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();
                    //判断注解是否为@EventType
                    if (annotationType.isAnnotationPresent(EventType.class)) {
                        //获取EventType注解
                        EventType eventType = annotationType.getAnnotation(EventType.class);
                        assert eventType != null;
                        //获取方法的Class
                        Class methodClass = eventType.methodClass();
                        //获取方法名
                        String methodName = eventType.methodName();
                        //设置访问权限
                        method.setAccessible(true);

                        try {
                            //获取OnClick或OnLongClick的value值
                            Method valueMethod = annotationType.getDeclaredMethod("value");
                            //获取绑定的id
                            int[] viewIds = (int[]) valueMethod.invoke(annotation);
                            //代理对象
                            Object proxy = Proxy.newProxyInstance(methodClass.getClassLoader(),
                                    new Class[]{methodClass},
                                    new InvocationHandler() {
                                        @Override
                                        public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
                                            return method.invoke(activity, args);
                                        }
                                    });
                            assert viewIds != null;
                            //遍历id并绑定事件
                            for (int id : viewIds) {
                                //获取Activity的View
                                View view = activity.findViewById(id);
                                //获取指定方法,如setOnClickListener方法,参数类型是OnClickListener
                                Method 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;

    @Override
    protected 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;
    }
}

代码下载

到了这里,关于Android 基于反射实现简易版ButterKnife的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android开发:kotlin语言实现简易计算器

    输入两个数字,可选加减乘除操作符,并计算显示对应结果 随系统切换语言 可对结果进行四舍五入操作 界面布局:activity_main.xml文件代码 字符定义:string.xml文件代码 逻辑实现:MainActivity.kt 文件代码 方法一(偷懒): 复制文件到对应位置 方法二: 1. 绘制界面 2. 编写逻辑

    2023年04月08日
    浏览(48)
  • 【Android Studio】实现简易猴子摘桃功能

    appsrcmainAndroidManifest.xml appsrcmainjavacomexamplepeachMainActivity.java appsrcmainjavacomexamplepeachPeachActivity.java appsrcmainresvaluesthemes.xml appsrcmainreslayoutactivity_main.xml appsrcmainreslayoutactivity_peach.xml      

    2024年02月06日
    浏览(49)
  • 基于qt的简易聊天实现

    本次项目采用的是TCP传输文件,UDP实现聊天以及聊天状态的反馈。 一、首先运行程序会进入到这样一个会话界面,也就是新加入一个用户,新加入的用户会在右侧显示其用户名、主机名和IP地址,在消息记录框中也会提示在线信息。 二、消息字体样式、字体大小、加粗、斜体

    2024年02月11日
    浏览(38)
  • 实现基于UDP简易的英汉词典

    实现一个服务端和一个客户端,客户端负责发送一个单词,服务端接收到后将翻译后的结果返回发送到客户端。 使用UDP网络连接,可以跨主机实现通信 。 服务端读取文件中保存的单词及其翻译,通过发送信号使服务端更新词库,不需要重启。 创建套接字文件,在Linux一切皆

    2024年02月15日
    浏览(34)
  • 基于HDFS实现的简易云盘系统

    基于HDFS的云盘系统实现了云盘的基本数据存储和访问功能。此为大二下大数据平台与架构的综合实验内容,本文旨在记录过程和问题,固然存在很多不合理的地方。 云盘系统通过互联网为企业和个人提供信息的存储、读取、下载等服务。具有安全稳定、海量等特点。目前,

    2024年02月04日
    浏览(34)
  • 基于ElasticSearch+Vue实现简易搜索

    基于ElasticSearch+Vue实现简易搜索 一、模拟数据 产品名称 描述 价格 库存数量 品牌名称 智能手表 智能手表,具有健康跟踪和通知功能。 199.99 1000 TechWatch 4K智能电视 4K分辨率智能电视,提供出色的画质。 699.99 500 VisionTech 无线耳机 降噪无线耳机,提供高品质音频体验。 149.99

    2024年02月04日
    浏览(36)
  • 基于Python 简易实现接口测试自动化

    目录 实现思路 统筹脚本 请求封装  日志封装 结果比对 结果邮件 用例获取及数据格式化 请求url转换 测试用例excel结构 测试报告 邮件接收结果 资料获取方法 使用excel管理用例用例信息,requests模块发送http请求,实现了记录日志,邮件发送测试报告的功能 目录结构如下: 下

    2024年02月13日
    浏览(44)
  • 基于HDFS实现的简易云盘系统(代码开源)

    基于HDFS的云盘系统实现了云盘的基本数据存储和访问功能。此为大二下大数据平台与架构的综合实验内容,本文旨在记录过程和问题,固然存在很多不合理的地方。 云盘系统通过互联网为企业和个人提供信息的存储、读取、下载等服务。具有安全稳定、海量等特点。目前,

    2024年02月04日
    浏览(39)
  • 基于XDMA的简易FPGA网卡实现(一)

    FPGA开发板 XC7K325T CPU RK3399 开发主机 Win11 and ubuntu20.04 IDE版本 Xilinx Vitis IDE v2021.1.0 (64-bit) Vivado v2021.1 (64-bit) FPGA侧 top 模块:顶层模块,其中例化了xmda和axil_rw模块 xdma ip:pcie dma,提供axi-lite接口读写fpga寄存器,提供axi-stream接口收发数据流 axil_rw 模块:将xdma的axi-lite信号用于读

    2024年04月16日
    浏览(27)
  • 基于python tornado实现的简易图床

    项目地址 因为买了阿里/腾讯的云服务器,但是使用云存储还需要收费,又加上家里正好有一台 nas ,又加上闲的没事,所以搞了一个小脚本 这个项目主要功能是为 typora 增加一个自定义图床 欢迎提出issues和pr,如果闲的没事会考虑增加一个web界面来上传图片 环境为:python3

    2024年02月14日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包