当前位置: 首页 > 知识库问答 >
问题:

Android ICS:无法处理回调;接口未实现,回调:android.view.view$PerformClick@40D80CC8

秦才英
2023-03-14

我正在ICS设备上体验非常怪异的行为。我有一个按钮在布局和单击Listener作为贝娄。

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button b = (Button) findViewById(R.id.button1);
    b.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
        // To just demonstrate weird behavior, i am throwing run-time exception 
         throw new RuntimeException("testing weird behavior on ICS");

         //String s = null;   s.length(); You can try this , application does not crash.
        } 
    });
}

在正常情况下,这应该会使应用程序崩溃,但令人惊讶的是,我可以看到logcat中出现崩溃,但应用程序没有崩溃。相反,我看到了

Failed to handle callback; interface not implemented, callback:android.view.View$PerformClick@40d80cc8
java.lang.RuntimeException: testing weird  behaviour
     at com.example.sampleproject.MainActivity$1.onClick(MainActivity.java:21)
     at android.view.View.performClick(View.java:3538)
     at android.view.View$PerformClick.run(View.java:14330)
     at android.os.Handler.handleCallback(Handler.java:608)
     at android.os.Handler.dispatchMessage(Handler.java:92)
     at android.os.Looper.loop(Looper.java:154)
     at android.app.ActivityThread.main(ActivityThread.java:4977)
     at java.lang.reflect.Method.invokeNative(Native Method)
     at java.lang.reflect.Method.invoke(Method.java:511)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
     at dalvik.system.NativeStart.main(Native Method)

任何想法为什么我正在经历这种怪异的行为,任何帮助是感激的。

共有1个答案

萧辰沛
2023-03-14

是否检查按钮b是否为空?由于logcat声明java.lang.NullPointerException,奇怪的是您遇到了这个问题,我通常遇到的是:

_btnFoo = (Button)findViewById(R.id.btnFoo);
if (_btnFoo != null){
   _btnFoo.setOnClickListener(new OnClickListener(){
      @Override
      public void onClick(View v){
         ....
      }
   });
}

null指针异常就像拇指痛一样突出,所以没有初始化它。

编辑:由于我的回答不够充分,我想到了从ICS 4.0.3回购中挖掘一些源代码,这是在Frameworks/base/core/java/android/view/view.java中的第14103行找到的代码部分

private final class PerformClick implements Runnable {
    public void run() {
        performClick();
    }
}

该方法的主要内容是在同一来源的第3505行中发现的:

public boolean performClick() {
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);

        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnClickListener != null) {
            playSoundEffect(SoundEffectConstants.CLICK);
            li.mOnClickListener.onClick(this);
            return true;
        }

        return false;
    }

我的猜测是 PerformClick中的 Runnable有问题,因为它似乎是跨线程,没有任何 RunonuithRead或类似保护措施的提示。

我要强调一下,在前面的句子中--我会打一个开放式问号,并在单词的意义上使用它,如,不是字面意思。

Jen的评论被证明是正确的,如这里所示,取自第3010行:

case R.styleable.View_onClick:
    if (context.isRestricted()) {
        throw new IllegalStateException("The android:onClick attribute cannot "
                + "be used within a restricted context");
    }

    final String handlerName = a.getString(attr);
    if (handlerName != null) {
        setOnClickListener(new OnClickListener() {
            private Method mHandler;

            public void onClick(View v) {
                if (mHandler == null) {
                    try {
                        mHandler = getContext().getClass().getMethod(handlerName,
                                View.class);
                    } catch (NoSuchMethodException e) {
                        int id = getId();
                        String idText = id == NO_ID ? "" : " with id '"
                                + getContext().getResources().getResourceEntryName(
                                    id) + "'";
                        throw new IllegalStateException("Could not find a method " +
                                handlerName + "(View) in the activity "
                                + getContext().getClass() + " for onClick handler"
                                + " on view " + View.this.getClass() + idText, e);
                    }
                }

                try {
                    mHandler.invoke(getContext(), View.this);
                } catch (IllegalAccessException e) {
                    throw new IllegalStateException("Could not execute non "
                            + "public method of the activity", e);
                } catch (InvocationTargetException e) {
                    throw new IllegalStateException("Could not execute "
                            + "method of the activity", e);
                }
            }
        });
    }
    break;

在第3452行,setonclicklistener方法是注册回调的地方,如图所示:

public void setOnClickListener(OnClickListener l) {
    if (!isClickable()) {
        setClickable(true);
    }
    getListenerInfo().mOnClickListener = l;
}

OP问题的答案是,框架中有一个bug,正如Jens简明扼要地说的那样,它至少是错误处理方面的一个差异。通常情况下,不应该在onclick中抛出异常--但我可以想象,如果在单击处理程序中做大量工作的应用程序上没有返回强制关闭报告,那么这会使跟踪“野生”错误变得更加困难。

 类似资料:
  • 本文向大家介绍java 接口回调实例详解,包括了java 接口回调实例详解的使用技巧和注意事项,需要的朋友参考一下 java 接口回调实例详解 首先官方对接口回调的定义是这样的,所谓回调:就是A类中调用B类中的某个方法C,然后B类中反过来调用A类中的方法D,D这个方法就叫回调方法。这样听起来有点绕,我们可以这么理解接口回调:比如我们想知道隔壁老王啥时候回家?但是我们有自己的事情做不能一直监视着老王

  • 问题内容: 我需要使用“接口”在Java中实现回调函数。我已经将应用程序部分写为 m_GetSizeInterface是一个包含回调函数GetSize的接口。此GetSize方法在应用程序中被覆盖。在JNI中,我需要调用具有原型的CPP函数 如何将此GetSize作为参数传递给JNI中的MyCPPFunction?请帮忙 问题答案: 这里的复杂之处在于您要调用本机C ++代码,而您又要调用Java

  • 从我的中,每个项目中都有多个按钮,我想要的是在单击,并在单击。 问题是我不知道如何才能或如何才能实现一个回调时被点击,并可以执行不同的方法或操作根据什么按钮是点击每个项目。 在我的适配器类上 这是我的DialogFragment类

  • 版本: 1.4.1 日期: 2021-01-14 当直播开始、结束和录制开始、结束、完成后,直播系统会通过用户在admin配置的回调信息以GET⽅式发起回调。若⽤户网站地址使⽤HTTPS协议进⾏数据安全传输时,⽤户需保证其拥有的CA证书是合法的。 ⽤户可以在admin后台指定的回调符合以下四种格式之⼀即为合法: 1、http://domain 2、http://domain?data=****(d

  • 问题内容: 我正在使用以下node.js代码从某些url下载文档并将其保存在磁盘中。我想知道何时下载该文档。我没有看到使用pipe进行任何回调。或者,下载完成后是否可以捕获任何“结束”事件? 问题答案: 流是,因此您可以听某些事件。如您所说,有一个请求事件(以前是)。 有关可用的事件的更多信息,请查看流文档页面。

  • 本文向大家介绍深入理解Android之接口回调机制,包括了深入理解Android之接口回调机制的使用技巧和注意事项,需要的朋友参考一下 刚开始学对于这个机制理解不够深刻,现在重新整理下思路。开发中,接口回调是我们经常用到的。 接口回调的意思即,注册之后并不立马执行,而在某个时机触发执行。 首先解决啥是回调: 举个例子:某天,我打电话向你请教问题,当然是个难题,你一时想不出解决方法,我又不能拿着电话