Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/201.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何获取视图的侦听器_Android_Listener - Fatal编程技术网

Android 如何获取视图的侦听器

Android 如何获取视图的侦听器,android,listener,Android,Listener,我编写与其他应用程序交互的服务。它在已经有侦听器的视图(按钮、文本视图等)上注册侦听器。我需要用我自己的侦听器(works)替换它们,做一些事情,然后注销我的侦听器并恢复旧的侦听器 正在运行带有onClickListener按钮的应用程序 我的服务在UI线程内注册onClickListener+执行某些操作 我的服务恢复旧的侦听器 如果有一个view.getOnClickListener-方法,这将很容易。然后,我可以保存旧的,并在完成后替换新的侦听器 有没有办法从一个视图中获取侦听器,或者将多

我编写与其他应用程序交互的服务。它在已经有侦听器的视图(按钮、文本视图等)上注册侦听器。我需要用我自己的侦听器(works)替换它们,做一些事情,然后注销我的侦听器并恢复旧的侦听器

  • 正在运行带有onClickListener按钮的应用程序
  • 我的服务在UI线程内注册onClickListener+执行某些操作
  • 我的服务恢复旧的侦听器
  • 如果有一个
    view.getOnClickListener
    -方法,这将很容易。然后,我可以保存旧的,并在完成后替换新的侦听器

    有没有办法从一个视图中获取侦听器,或者将多个相同类型的侦听器绑定到一个视图

    Button btn = (Button) findViewById(R.id.btn1);
    btn.setOnClickListener(new OnClickListener() {
    
            public void onClick(View v) {
                //do something
            }
        });
    // I need to do, but found no solution for that.
    View.OnClickListener oldListener = btn.getOnClickListener();
    
    如果我将新的侦听器注册到视图中,旧的侦听器将被覆盖,对吗?如果两个侦听器(“新的”和“旧的”)同时存在也可以。只有旧的不能消失

    编辑:不幸的是,我无法在分配时保存侦听器。我需要从视图组件中向后获取它


    谢谢

    制作两个OnCLickListener实例,并将第一个或第二个实例分配给按钮:

        Button b = (Button) findViewById(R.id.Button1);
    
        OnClickListener listener_new =  new OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("APP", "NEW CLICK LISTENER ACTIVE");
            }
        };
    
        OnClickListener listener_old =  new OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("APP", "OLD CLICK LISTENER ACTIVE");
            }
        };
    
        //setting listener
        b.setOnClickListener(listener_old);
        b.callOnClick();
    
                //changing listener
        b.setOnClickListener(listener_new);
        b.callOnClick();
    
                //return your old listener!
            b.setOnClickListener(listener_old);
            b.callOnClick();
    
    增加:

    OnClickListener是Button类的受保护字段,继承自View类。字段“mOnClickListener”的名称。我甚至无法通过思考得到它

    void getListener(Button b) {
    java.lang.reflect.Field field =  getClass().getSuperclass().getSuperclass().getDeclaredField("mOnClickListener");
    }
    
    因此,如果您无法访问按钮创建位置的代码,则无法获取按钮的现有侦听器


    但如果您有权访问活动对象(我们知道您有权访问,因为将new listener设置为button),您可以在该活动上添加按钮和侦听器。使现有按钮不可见。然后在必要时回滚。

    创建实现OnClickListener的类

    public static class MyClickListener1 implements OnClickListener{
        Activity mActivity;
        MyClickListener1(Acivity activity){
          mActivity=activity;
        }
        @Override
        public void onClick(View v) {
                //do something
        }
    }
    
    public static class MyClickListener2 implements OnClickListener{
        @Override
        public void onClick(View v) {
                //do something
        }
    }
    
    在您的代码中,您可以轻松地使用它们:

    btn.setOnClickListener(new MyClickListener1(this));
    btn.setOnClickListener(new MyClickListener2());
    
    或者,您可以创建实例并重用它们:

    btn.setOnClickListener(new MyClickListener1(this));
    btn.setOnClickListener(new MyClickListener2());
    
    OnClickListener listener1 = new MyClickListener1(this);
    OnClickListener listener2 = new MyClickListener2();
    btn.setOnClickListener(listener1);
    btn.setOnClickListener(listener2);
    
    您还可以定义一个构造函数来传递这些类中需要的任何内容。我通常通过
    MyClickListener1

    编辑:如果希望按钮中有类似侦听器的对象,可以使用标记

    btn.setTag(listener1);
    btn.setOnClickListener(listener1);
    
    然后使用它

    OnClickListener old_listener = (OnClickListenr)btn.getTag();
    
    感谢mihail对隐藏API的提示(谢谢:)),我找到了一个解决方案,可以在分配任务后让侦听器返回:

    android.view.view类有一个嵌套类
    静态类ListenerInfo
    ,它将所有侦听器存储在一个视图上(API 14+)。在旧版本中,监听器是
    android.view.view
    中的私有字段

    该字段可以通过反射进行访问。就我而言(API 14+)

    在那段代码之后(我错过了很多try-catch块),myListener对象保存了onClickListener的实例,该实例之前已匿名声明给视图。它也适用于任何其他侦听器,只需将“mOnClickListener参数”替换为反射中所需的参数并正确地强制转换即可

    请注意,即将发布的版本中的代码更改可能会使其不再工作

    在这里找到了最终教程:

    公共抽象类ReflectionUtils{
    私有静态最终字符串listenerInfoFieldName=“mListenerInfo”;
    私有静态最终字符串onCLickListenerFieldName=“mOnClickListener”;
    公共静态OnClickListener getOnClickListener(视图){
    Object listenerInfo=ReflectionUtils.getValueFromObject(视图,listenerInfoFieldName,Object.class);
    返回ReflectionUtils.getValueFromObject(listenerInfo、onCLickListenerFieldName、View.OnClickListener.class);
    }
    公共静态T getValueFromObject(对象对象、字符串字段名、类returnClazz){
    返回getValueFromObject(object,object.getClass(),fieldName,returnClazz);
    }
    私有静态T getValueFromObject(对象对象、类declaredFieldClass、字符串字段名、类returnClazz){
    试一试{
    Field Field=declaredFieldClass.getDeclaredField(fieldName);
    字段。setAccessible(true);
    对象值=field.get(对象);
    返回返回clazz.cast(值);
    }捕获(无此字段例外){
    Class superClass=declaredFieldClass.getSuperclass();
    if(超类!=null){
    返回getValueFromObject(对象、超类、字段名、returnClazz);
    }
    }捕获(非法访问例外e){
    }
    返回null;
    }
    }
    

    调用
    OnClickListener OnClickListener=ReflectionUtils.getOnClickListener(myView)myView
    上的code>将为您提供您正在寻找的
    myView
    的侦听器。

    您不能通过setOnClickListener方法设置旧的侦听器吗<代码>setOnClickListener(旧侦听器)否,因为我只知道服务“控制/挂接(通过检测)”的应用程序的小部件。因此,我无法在分配旧侦听器时保存它,因为我没有应用程序的src代码。有了指令插入,我可以获得所有的小部件、按钮等,但我还需要当前的活动侦听器。希望这能让问题变得更清楚。嗨,朋友,你做到了吗?我想做同样的事情@dr.AtZeThanks,但这对我来说不起作用,因为我无法访问应用程序,而该应用程序是为侦听器分配的。我需要后面的监听器和仪器。有了它,我可以得到按钮、视图等等,但我还需要它们的侦听器在插入后恢复它们。否则,当我的指令插入完成后,应用程序将不再可控。我错过了自定义侦听器仍然用它替换旧的侦听器。因此,在您的示例中,
    listener2
    始终替换
    listener1
    。如果旧的仍然存在那就太好了,因为我对第一个侦听器的分配位置的源代码没有影响。我只使用仪器获取视图。所以,当我没有把它保存在crea上时,不存在找回一个听众的“魔力”
    public abstract class ReflectionUtils {
    
        private static final String listenerInfoFieldName = "mListenerInfo";
        private static final String onCLickListenerFieldName = "mOnClickListener";
    
        public static OnClickListener getOnClickListener(View view){
            Object listenerInfo = ReflectionUtils.getValueFromObject(view, listenerInfoFieldName, Object.class);
            return ReflectionUtils.getValueFromObject(listenerInfo, onCLickListenerFieldName, View.OnClickListener.class);
        }
    
        public static <T> T getValueFromObject(Object object, String fieldName, Class<T> returnClazz){
            return getValueFromObject(object, object.getClass(), fieldName, returnClazz);
        }
    
        private static <T> T getValueFromObject(Object object, Class<?> declaredFieldClass, String fieldName, Class<T> returnClazz){
            try {
                Field field = declaredFieldClass.getDeclaredField(fieldName);
                field.setAccessible(true);
                Object value = field.get(object);
                return returnClazz.cast(value);
            } catch (NoSuchFieldException e) {
                Class<?> superClass = declaredFieldClass.getSuperclass();
                if(superClass != null){
                    return getValueFromObject(object, superClass, fieldName, returnClazz);
                }
            } catch (IllegalAccessException e) {
            }
            return null;
        }
    
    }