InflateException: Couldn't resolve menu item onClick handler

99封情书 提交于 2019-12-17 18:27:57

问题


I asked this question 6 years ago. In the meantime Android development best practices have changed, and I have become a better developer.

Since then, I have realized that using the onClick XML attribute is a bad practice, and have removed it from any code base I work on.

All of my click handlers are now defined in the code of the app, not the XML layouts!

My reasons for never using onClick are

  1. it is easy to make a mistake in the value of the onClick XML attribute, which will then result in a run-time error
  2. a developer might refactor the name of the click handler method, without realizing it is called from a layout (see reason 1)
  3. finding out which method is actually being called is not always obvious. Especially if the layout is being used by a Fragment
  4. separating the concerns of layout vs behavior is good. Using onClick mixes them up, which is bad!

I hope I have convinced you to never use onClick in a layout :) !

Below is my original question, which is a pretty good illustration of why using onClick is a bad idea.

===

I'm defining menu items in XML, and trying to use the onClick attribute that was added in API 11. When the Activity is launched in an emulator running 4.0.3, the following Exceptions occur:

FATAL EXCEPTION: main
android.view.InflateException: Couldn't resolve menu item onClick handler 
    onFeedbackMenu in class android.view.ContextThemeWrapper

...
Caused by: java.lang.NoSuchMethodException: onFeedbackMenu 
    [interface com.actionbarsherlock.view.MenuItem]
at java.lang.Class.getConstructorOrMethod(Class.java:460)

I don't understand what is causing the Exception, since the following method is defined in my Activity

import com.actionbarsherlock.view.MenuItem;
...
public void onFeedbackMenu( MenuItem menuItem ) { 
    Toast.makeText( this, "onFeedBack", Toast.LENGTH_LONG ).show();
}

My XML menu definition file contains:

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
...
    <item
        android:id="@+id/menu_feedback"
        android:icon="@drawable/ic_action_share"
        android:showAsAction="ifRoom"
        android:title="@string/menu_feedback"
        android:onClick="onFeedbackMenu" />
</menu>

For backwards compatibility I am using ActionBarSherlock, and also getting a very similar Exception when I run the App on 2.3.x.

This is a more Complete version of the Stack trace

FATAL EXCEPTION: main
android.view.InflateException: Couldn't resolve menu item onClick handler 
    onFeedbackMenu in class android.view.ContextThemeWrapper
    at com.actionbarsherlock.view.MenuInflater$InflatedOnMenuItemClickListener.<init>(MenuInflater.java:204)
    at com.actionbarsherlock.view.MenuInflater$MenuState.setItem(MenuInflater.java:410)
    at com.actionbarsherlock.view.MenuInflater$MenuState.addItem(MenuInflater.java:445)
    at com.actionbarsherlock.view.MenuInflater.parseMenu(MenuInflater.java:175)
    at com.actionbarsherlock.view.MenuInflater.inflate(MenuInflater.java:97)
    ...
Caused by: java.lang.NoSuchMethodException: onFeedbackMenu 
    [interface com.actionbarsherlock.view.MenuItem]
    at java.lang.Class.getConstructorOrMethod(Class.java:460)
    at java.lang.Class.getMethod(Class.java:915)
    at com.actionbarsherlock.view.MenuInflater$InflatedOnMenuItemClickListener.<init>(MenuInflater.java:202)
    ... 23 more

回答1:


I found a solution that worked for me. Usually the onClick attribute in a layout has the following method

public void methodname(View view) { 
    // actions
}

On a menu item (in this case Sherlock menu) it should follow the following signature:

public boolean methodname(MenuItem item) { 
    // actions
}

So, your problem was that your method returned void and not boolean.




回答2:


In my case, the AndroidManifest.xml of my application (kick-started by the default Eclipse assistant) contained android:theme="@style/AppTheme" in the <application> block.

When debugging the cause of the problem, it turned out that the line

mMethod = c.getMethod(methodName, PARAM_TYPES);

in android.view.MenuInflater/InflatedOnMenuItemClickListener was called with c not being my Activity class but a dubious android.view.ContextThemeWrapper (which of course doesn't contain the onClick handler).

So, I removed the android:theme and everything worked.




回答3:


Although this is a bit out of date, here is the reason for the exception. When you look into the sources of android API 15 (4.0.3-4.0.4) in the class MenuInflater you will see this method:

public InflatedOnMenuItemClickListener(Context context, String methodName) {
mContext = context;
Class<?> c = context.getClass();
try {
    mMethod = c.getMethod(methodName, PARAM_TYPES);
} catch (Exception e) {
    InflateException ex = new InflateException(
            "Couldn't resolve menu item onClick handler " + methodName +
            " in class " + c.getName());
    ex.initCause(e);
    throw ex;
}

This is were the exception happens, as Junique already pointed out. However the removing of the app theme is just a workaround and no real option. As we see the method tries to find the Callback method on the class of the context item passed. So instead of calling getMenuInflater() in onCreateOptionsMenu you should call new MenuInflater(this), so that this is passed as a context and then the code will work.

You can still use getMenuInflater() for other api versions if you just use an if statement like this:

if (Build.VERSION.SDK_INT > 15)
        inflater = getMenuInflater();
    else
        inflater = new MenuInflater(this);

I don't actually know if the bug happens in api versions under 15 too, so i just generally used the save version.




回答4:


In my case the problem was that I had both onClick in my menu XML and an onCreateOptionsMenu in my Activity. My onClick was actually faulty (because it pointed to non-existent methods) but I didn't notice this at first because I was testing under Android 2.x, where onClick is not supported and ignored. Once I tested on 4.x though, I started getting this error.

So basically, don't use onClick if you plan on deploying under Android 2.x. It will silently ignore your onClick values until you try running on 3.0+.




回答5:


I found that I had the same problem with the ActionBar menu items, and their onClick events. What i discovered is that the workstation I'm developing in had run out of memory and needed to be rebooted. The Android VM is now able to resolve the method name referenced.




回答6:


Your method must accept a MenuItem as its only parameter per here.

    public void onMenuItemClickMethod(MenuItem menuItem){
        // Do stuff here
    }



回答7:


@Override
public boolean onCreateOptionsMenu(Menu menu) 
{
    getMenuInflater().inflate(R.menu.activity_main, menu);

    MenuItem item = menu.findItem(R.id.menu_open);

    if (item == null)
        return true;

    item.setOnMenuItemClickListener
    (
        new MenuItem.OnMenuItemClickListener () 
        { 
            public boolean onMenuItemClick(MenuItem item) 
            { return (showDirectory(item)); }
        } 
    ); 

    return true;
}


public boolean showDirectory (MenuItem item)
{
    CheckBox checkBox = (CheckBox) findViewById (R.id.checkBox1);
    checkBox.setChecked(true);
}


来源:https://stackoverflow.com/questions/11245829/inflateexception-couldnt-resolve-menu-item-onclick-handler

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!