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

Я определяю элементы меню в XML и пытаюсь использовать атрибут onClick, добавленный в API 11. Когда действие запускается в эмуляторе с запуском 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 

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

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

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

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

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

В моем случае приложение 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 и все сработало.

Хотя это немного устарело, вот причина исключения. Когда вы изучаете источники андроида 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; } 

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

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

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

Я действительно не знаю, произошла ли ошибка в api-версиях до 15 лет, поэтому я просто использовал версию сохранения. Не может быть проблематично.

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

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

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

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