it-swarm.com.ru

InflateException: не удалось разрешить пункт меню в обработчике клика

Я задал этот вопрос 6 лет назад. За это время передовые практики разработки под Android изменились, и я стал лучшим разработчиком.

С тех пор я понял, что использование XML-атрибута onClick - плохая практика, и удалил его из любой базы кода, над которой я работаю.

Все мои обработчики кликов теперь определены в коде приложения, а не в макетах XML!

Мои причины никогда не использовать onClick

  1. легко допустить ошибку в значении атрибута XML onClick, что приведет к ошибке во время выполнения
  2. разработчик может реорганизовать имя метода обработчика кликов, не осознавая, что он вызывается из макета (см. причину 1)
  3. выяснить, какой метод на самом деле вызывается, не всегда очевидно. Особенно, если макет используется фрагментом
  4. разделение проблем макета против поведения - это хорошо. Использование onClick смешивает их, что плохо! 

Я надеюсь, что убедил вас никогда не использовать onClick в макете :)!

Ниже мой оригинальный вопрос, который является довольно хорошей иллюстрацией того, почему использование onClick является плохой идеей.

===

Я определяю пункты меню в XML и пытаюсь использовать атрибут onClick, который был добавлен в API 11. Когда Activity запускается в эмуляторе под управлением 4.0.3, возникают следующие исключения:

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)

Я не понимаю, что является причиной исключения, так как в моей деятельности определен следующий метод

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

Мой файл определения меню XML содержит:

<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>

Для обратной совместимости я использую ActionBarSherlock, а также получаю очень похожее исключение при запуске приложения на 2.3.x.

Это более полная версия трассировки стека

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
35
Frank Harper

Я нашел решение, которое сработало для меня . Обычно атрибут onClick в макете имеет следующий метод

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

В пункте меню (в данном случае в меню «Шерлок») должна следовать следующая подпись:

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

Итак, ваша проблема заключалась в том, что ваш метод возвратил void, а не boolean.

72
Milagaia

В моем случае AndroidManifest.xml моего приложения (запущенного по умолчанию помощником Eclipse) содержал Android:theme="@style/AppTheme" в блоке <application>.

При отладке причины проблемы оказалось, что строка

mMethod = c.getMethod(methodName, PARAM_TYPES);

в Android.view.MenuInflater/InflatedOnMenuItemClickListener вызывался с c не моим классом Activity, а сомнительным Android.view.ContextThemeWrapper (который, конечно, не содержит обработчик onClick).

Итак, я удалил Android:theme и все заработало.

16
junique

Хотя это немного устарело, вот причина для исключения. Когда вы посмотрите на источники Android API 15 (4.0.3-4.0.4) в классе MenuInflater, вы увидите этот метод:

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;
}

Это было исключение, как уже указала Юник. Однако удаление темы приложения - это просто обходной путь, а не реальный вариант. Как мы видим, метод пытается найти метод Callback в классе передаваемого элемента контекста. Поэтому вместо вызова getMenuInflater() в onCreateOptionsMenu вы должны вызвать new MenuInflater(this), чтобы this передавался как контекст, а затем код работал.

Вы все еще можете использовать getMenuInflater() для других версий API, если вы просто используете оператор if, подобный этому:

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

На самом деле я не знаю, происходит ли ошибка в версиях API под 15, поэтому я просто использовал версию сохранения.

9
findusl

В моем случае проблема заключалась в том, что у меня был и onClick в моем меню XML, и onCreateOptionsMenu в моей деятельности. Мой onClick был фактически неисправен (потому что он указывал на несуществующие методы), но я сначала не заметил этого, потому что я тестировал под Android 2.x, где onClick не поддерживается и игнорируется. После того, как я проверил на 4.x, я начал получать эту ошибку.

В общем, не используйте onClick, если вы планируете развертывать под Android 2.x. Он будет игнорировать ваши значения onClick до тех пор, пока вы не попробуете запустить 3.0+.

1
Matt Zukowski

Я обнаружил, что у меня была та же проблема с элементами меню ActionBar и их событиями onClick. Я обнаружил, что на рабочей станции, на которой я работаю, не хватило памяти, и ее необходимо перезагрузить. Android VM теперь может разрешать имя метода, на которое ссылаются.

0
user1418015
@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);
}
0
user1418015

Ваш метод должен принять MenuItem в качестве единственного параметра для здесь .

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