播放商店崩溃报告:android.view.View $ DeclaredOnClickListener.onClick上的IllegalStateException [英] Play Store Crash Report: IllegalStateException on android.view.View$DeclaredOnClickListener.onClick

查看:95
本文介绍了播放商店崩溃报告:android.view.View $ DeclaredOnClickListener.onClick上的IllegalStateException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的一个应用程序为IllegalStateException提取了一些崩溃报告.堆栈跟踪说它来自android.view.View $ DeclaredOnClickListener.onClick(view).我从未在测试或日常使用中遇到此错误(我使用

One of my apps picked up some crash reports for IllegalStateException. The Stack Traces say it's coming from android.view.View$DeclaredOnClickListener.onClick(view). I have never come across this error in my testing or daily use (I use the app myself on a daily basis on a Samsung Note 4 running Android 6.0.1). Honestly I don't know where to begin to look because the Stack Trace doesn't seem to even refer to any of my own code, just platform code. What am I missing? This version does use the support library, but not fragments, which is where other solutions to this error have been referring to.

下面,我粘贴了堆栈跟踪之一.这是来自运行Android 6.0的Moto G Turbo

Below I've pasted one of the Stack Traces. This is from a Moto G Turbo running Android 6.0

java.lang.IllegalStateException: 
  at android.view.View$DeclaredOnClickListener.onClick(View.java:4455)
  at android.view.View.performClick(View.java:5201)
  at android.view.View$PerformClick.run(View.java:21163)
  at android.os.Handler.handleCallback(Handler.java:746)
  at android.os.Handler.dispatchMessage(Handler.java:95)
  at android.os.Looper.loop(Looper.java:148)
  at android.app.ActivityThread.main(ActivityThread.java:5443)
  at java.lang.reflect.Method.invoke(Native Method:0)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
Caused by: java.lang.reflect.InvocationTargetException: 
  at java.lang.reflect.Method.invoke(Native Method:0)
  at android.view.View$DeclaredOnClickListener.onClick(View.java:4450)

推荐答案

很抱歉,答案很长,但我认为它对解释如何深入研究Android框架以调试问题很有用.

Sorry for the long answer but I think its useful to explain how to dig into the Android framework to debug the problem.

引发此异常的代码可以在此处访问:

The code that throws this exception can be accessed here:

http://androidxref. com/6.0.1_r10/xref/frameworks/base/core/java/android/view/View.java

4452            try {
4453                mMethod.invoke(mHostView.getContext(), v);
4454            } catch (IllegalAccessException e) {
4455                throw new IllegalStateException(
4456                        "Could not execute non-public method for android:onClick", e);
4457            } catch (InvocationTargetException e) {
4458                throw new IllegalStateException(
4459                        "Could not execute method for android:onClick", e);
4460            }

反射及其在点击侦听器中的使用

基本上,它的工作是使用反射调用基于字符串的方法.此方法是应用程序开发人员定义的一种方法,用于响应单击的按钮.通常可以这样做,因为您可以通过XML指定onClickListener方法,例如,您可以说调用"goDoWhatever"而不是通常的"onClick".反射使用此方法的字符串表示形式,并尝试在该名称的指定类上调用方法.

Basically what it is doing is invoking a method based on a string using reflection. This method is one that is defined by an app developer to respond to a button being clicked. This is commonly done since you can specify an onClickListener method via XML, for example you can say invoke "goDoWhatever" instead of the usual "onClick". Reflection takes a string representation of this method and tries to call a method on a specified class of that name.

当所需的方法不存在时(例如,如果您输入的名称错误,方法是私有的或参数不同),则会发生反射错误.

A reflection error occurs when the desired method does not exist, for example if you get the name wrong, the method is private, or the parameters are different.

请注意,在这种情况下,有两种不同的例外,一种是非公共方法,另一种是无法执行.我不知道为什么您的堆栈跟踪中没有与IllegalStateException相关的消息,但是制造商可以根据需要修改此代码.

Note that in this case there are two different exceptions, one for a non public method and then another for not being able to execute it. I don't know why your stack trace doesn't have a message associated with the IllegalStateException but manufacturers can modify this code if they desire.

我怀疑您有一个正确名称的方法,因为如果名称错误,resolve method函数会引发另一个错误:

I suspect that you have a method of the correct name since the resolve method function throws a different error if the name is wrong:

4463        @NonNull
4464        private Method resolveMethod(@Nullable Context context, @NonNull String name) {
4465            while (context != null) {
4466                try {
4467                    if (!context.isRestricted()) {
4468                        return context.getClass().getMethod(mMethodName, View.class);
4469                    }
                ...
4485            throw new IllegalStateException("Could not find method " + mMethodName
4486                    + "(View) in a parent or ancestor Context for android:onClick "
4487                    + "attribute defined on view " + mHostView.getClass() + idText);
4488        }
4489    }

因此,这给我们留下了两种我可以想到的可能性:发现的方法签名错误或发现的方法是静态/私有的.

So this leaves us with two possibilities that I can think of: the method it finds has the wrong signature or the method it finds is static/private.

我将如何进行调试:

我猜您在xml中的某个位置指定了一个点击侦听器(在xml文件中查找"android:onClick =.然后在您的应用程序中搜索所有相同名称的方法,并确保它们采用单个View作为一个参数(确保在文件中也导入了"android.view.View",因为导入错误的视图可能会导致此问题.)还请确保它们不是静态的.这样做也值得寻找私有的东西也会引起问题,但是根据您的堆栈跟踪,可能性似乎较小.

I am guessing you specify a click listener in your xml somewhere (look for "android:onClick=" in your xml files. Then search your application for all methods of the same name and make sure that they take a single View as a parameter (make sure you import "android.view.View" in the file too as importing the wrong view could cause this). Also make sure they are not static. It is also probably worth looking for things that are private as this can also cause problems but based on your stack trace it seems less likely.

为什么这个问题可能很难重现:

如果您注意到android框架中的方法"resolveMethod"仅返回了同名的第一个方法,那么拥有类是有效的java:

If you notice the method "resolveMethod" in the android framework simply returns the first method of the same name, so whereas it is valid java to have a class:

class Foo{
    void bar(String s){}
    void bar(View s){}

方法签名由名称(例如"bar")和参数列表组成(在这种情况下,列表中包含一个视图"项,或者列表中包含一个"String"项).

A method signature consists of a name (such as "bar") and a list of parameters, (in this case a list with one item "View" or a list with one item "String").

此Android框架代码可能会找到"void bar(String s)",而不是"void bar(View s)".这可能导致难以重现的错误,因为反射查找方法的顺序是不确定的(

This Android framework code might find "void bar(String s)" instead of "void bar(View s)". This can cause a hard to reproduce bug since the order in which reflection finds methods is non deterministic (Java reflection: Is the order of class fields and methods standardized?). So you may have a hard time reproducing it since a specific device probably deterministically iterates through them in some way but not neccessarily the same way as some other device/implementation.

我希望这会有所帮助!请让我知道结果,我是一名正在研究诸如此类的软件缺陷的研究生,因此详细信息对我很有用.

I hope this helps! Please let me know how it turns out, I am a graduate student doing research on software defects such as this one so details are quite useful to me.

这篇关于播放商店崩溃报告:android.view.View $ DeclaredOnClickListener.onClick上的IllegalStateException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆