Could not find a method onClick_Foo(View) - first

2020-02-27 08:00发布

问题:

I have an app that is about a year old, is on the Play store in beta, has gone through dozens of revisions. All of a sudden I'm getting an error:

Could not find a method onClick_Foo(View) in the activity class android.view.ContextThemeWrapper for onClick handler on view class android.widget.Button with id 'Foo_Button'

I'm getting this error on every one of the 7 buttons defined in my XML. Since yesterday I've updating appcompat-v7 from 21.0.3 to 22.0.0 but also upgraded my testing device from KitKat to Lollipop for the first time.

I've double-checked spellings, capitalizations, none of the usual suspects explains this. Here's a sample of the relevant code. Let me know if you feel more would be helpful. (The activity has 915 lines of code and the xml 186, so don't ask for the whole thing). Testing on a Verizon Note 4 running Lollipop 5.0.1

activity_pick.xml:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:theme="@style/AppTheme"
    tools:context="com.myapp.Pick"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:orientation="vertical">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/Ratings_Button"
            android:textSize="16dp"
            android:text="@string/Pick_Ratings_Button"
            android:onClick="onClick_Ratings"
            android:background="@android:drawable/btn_default"/>
</LinearLayout>
</ScrollView>

Pick.java:

public class Pick_Restaurant extends ActionBarActivity {
    public void onClick_Ratings (View v) {
        Intent intent = new Intent(mContext, Ratings.class);
        startActivityForResult(intent,RATINGS);
    }
}

build.gradle:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

defaultConfig {
    minSdkVersion 15
    targetSdkVersion 22
    versionCode 59
    versionName "0.6.4"
}

...

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.android.support:appcompat-v7:22.0.0'
    compile 'com.google.android.gms:play-services:7.0.0'
    compile files('libs/mobileservices-1.1.5.jar')
}

Full Error on Log:

04-08 17:06:40.578    3508-3508/com.myapp.debug E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.myapp.debug, PID: 3508
    java.lang.IllegalStateException: Could not find a method onClick_Ratings(View) in the activity class android.view.ContextThemeWrapper for onClick handler on view class android.widget.Button with id 'Ratings_Button'
            at android.view.View$1.onClick(View.java:4234)
            at android.view.View.performClick(View.java:5191)
            at android.view.View$PerformClick.run(View.java:20916)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:145)
            at android.app.ActivityThread.main(ActivityThread.java:5974)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1388)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1183)
     Caused by: java.lang.NoSuchMethodException: onClick_Ratings [class android.view.View]
            at java.lang.Class.getMethod(Class.java:665)
            at android.view.View$1.onClick(View.java:4227)
            at android.view.View.performClick(View.java:5191)
            at android.view.View$PerformClick.run(View.java:20916)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:145)
            at android.app.ActivityThread.main(ActivityThread.java:5974)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1388)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1183)

回答1:

It looks like this is a new issue with Android 5.0.

From this anwer, removing the Theme from the layout xml fixed this issue for them.

So in your case, remove the theme from your layout:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <!--android:theme="@style/AppTheme"--> <!-- Remove this -->
    <!--................-->
  </ScrollView>

And add the theme in the AndroidManifest.xml instead:

android:theme="@android:style/AppTheme"


回答2:

I have just answered a similar question here

Basically, since Android 5.0 individual views can be themed.

To facilitate this, a ContextThemeWrapper is used to modify the underlying theme assigned to the Activity and assigned as the Context of the View. Since this Context is not your Activity anymore (the Activity has to be separate because it still has to return the original theme) the callbacks don't exist and you get the error you see.

If you don't really want to theme individual views the obvious solution is to not do so and theme the activity instead, as already suggested.

If you do indeed want to theme individual views, it appears that the android:onClick attribute cannot be used and you will have to fall back to manually assign an OnClickListener.

The question is, why did this work pre Lollipop? I can only speculate that because the functionality to theme individual views didn't exist, applying a theme attribute to a view would just change the default theme on the Activity as well.



回答3:

Such things usually happens when you declare onClick in xml like you did:

android:onClick="onClick_Ratings"

Just make sure you are using this layout in that activity. Because the exception is clearly saying that your activity don't have the corresponding method which you did show you have:

public void onClick_Ratings (View v) {
    Intent intent = new Intent(mContext, Ratings.class);
    startActivityForResult(intent,RATINGS);
}

Also I guess you should declare the activity in your xml like:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".SendMessageActivity">

And actually log says:

Could not find a method onClick_Ratings(View) in the activity class android.view.ContextThemeWrapper

there is something wrong since android.view.ContextThemeWrapper is not an Activity and not the activity from your xml com.myapp.Pick (I assume Pick is an activity and not the fragment). Maybe try to clean up the project, ivalidate caches and restart.
If nothing helps I suggest you to return back to previuos version of support lib you'd mentioned OR to set onClickListener in code instead of xml.



回答4:

Removing android:theme works. But this is caused because using android:onclick in xml. If you use onClick in Java file, you can still use android:theme.

According to your code,

activity_pick.xml [Remove onclick here]

 <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/Ratings_Button"
        android:textSize="16dp"
        android:text="@string/Pick_Ratings_Button"        
        android:background="@android:drawable/btn_default" />

Go to your Java File, that is, pick.java in your case:

    final Button button = (Button) findViewById(R.id.Ratings_Button);

    button.setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {
            Intent activityChangeIntent = new Intent(CurrentActivity.this, SecondActivity.class);
            SplashScreen.this.startActivity(activityChangeIntent);
        }
    });

Experienced the same error, app has stopped working, when material button was clicked programmatically helped me. Check it out :)