抱歉回答太长,但我认为解释如何深入 Android 框架来调试问题很有用。
可以在此处访问引发此异常的代码:
http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/android/view/View.java 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”。反射采用此方法的字符串表示形式,并尝试调用该名称的指定类上的方法。
当所需的方法不存在时,例如名称错误、方法是私有的或参数不同,就会发生反射错误。
请注意,在这种情况下,有两种不同的异常,一种针对非公共方法,另一种针对无法执行该方法。我不知道为什么您的堆栈跟踪没有与 IllegalStateException 关联的消息,但制造商可以根据需要修改此代码。
我怀疑您有一个名称正确的方法,因为如果名称错误,解析方法函数会抛出不同的错误:
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 }
因此,这给我们留下了我能想到的两种可能性:它找到的方法有错误的签名,或者它找到的方法是静态/私有的。
我将如何调试这个:
我猜您在 xml 中的某处指定了一个点击侦听器(在 xml 文件中查找“android:onClick=”。然后在您的应用程序中搜索同名的所有方法,并确保它们采用单个 View 作为参数(确保您也在文件中导入“android.view.View”,因为导入错误的视图可能会导致这种情况)。还要确保它们不是静态的。可能还值得寻找私有的东西,因为这也可能导致问题但根据你的堆栈跟踪,它似乎不太可能。
为什么这个问题可能难以重现:
如果您注意到 android 框架中的方法“resolveMethod”只是返回同名的第一个方法,那么虽然 java 拥有一个类是有效的:
class Foo{
void bar(String s){}
void bar(View s){}
方法签名由名称(例如“bar”)和参数列表(在本例中为包含一项“View”的列表或包含一项“String”的列表)组成。
此 Android 框架代码可能会找到“void bar(String s)”而不是“void bar(View s)”。这可能会导致难以重现的错误,因为反射查找方法的顺序是不确定的(Java反思:类字段和方法的顺序是否标准化? https://stackoverflow.com/questions/1097807/java-reflection-is-the-order-of-class-fields-and-methods-standardized)。因此,您可能很难重现它,因为特定设备可能会以某种方式确定性地迭代它们,但不一定与其他设备/实现相同。
我希望这有帮助!请告诉我结果如何,我是一名研究生,正在研究诸如此类的软件缺陷,因此细节对我来说非常有用。