Android通过反射设置按钮的事件监听器

本文通过一个实例介绍了如何使用Java反射在Android中实现对按钮点击事件监听器的设置。通过跟踪setOnClickListener方法,理解其底层将监听器赋值给View的mListenerInfo.mOnClickListener,然后利用反射技术进行相应操作。

最近准备入门学习Android的hook框架,因为涉及到Java反射,于是就用这个例子来复习一下Java反射的应用吧。

首先确定我们要实现的效果是

btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(MainActivity.this, "fuc you", Toast.LENGTH_SHORT).show();
        }
});

跟进setOnClickListener方法,看看底下做了些什么:

    public void setOnClickListener(@Nullable OnClickListener l) {
        if (!isClickable()) {
            setClickable(true);
        }
        getListenerInfo().mOnClickListener = l;
    }
ListenerInfo getListenerInfo() {
    if (mListenerInfo != null) {
        return mListenerInfo;
    }
    mListenerInfo = new ListenerInfo();
    return mListenerInfo;
}
 static class ListenerInfo {
...
        public OnClickListener mOnClickListener;
...
    }

setOnClickListener方法最终将listener对象赋给了View的成员变量mListenerInfo里面的mOnClickListener成员变量,也就是

View.mListenerInfo.mOnClickListener = listener;

所以我们反射的思路是:

  1. 从btn中获取实例mListenerInfo;
  2. 设置mListenerInfo的属性mOnClickListener为我们自定义的listener

代码:

//反射修改监听器
Class viewClazz = View.class;
try {
    Field infoField = viewClazz.getDeclaredField("mListenerInfo");
    infoField.setAccessible(true);  //无视访问修饰符
    Object listenerInfo = infoField.get(btn);

    Class infoClazz = Class.forName("android.view.View$ListenerInfo");
    Field listenerField = infoClazz.getDeclaredField("mOnClickListener");
    listenerField.setAccessible(true);  //无视访问修饰符
    listenerField.set(listenerInfo, new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(MainActivity.this, "Hello!", Toast.LENGTH_SHORT).show();
        }
    });
} catch (Exception e) {
    e.printStackTrace();
}
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值