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

来源:互联网 发布:cypcut激光切割软件 编辑:程序博客网 时间:2024/05/22 01:52

最近准备入门学习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();}
阅读全文
0 0