Android 充气异常:无法';t解析菜单项onClick处理程序
我6年前问过这个问题。与此同时,Android开发最佳实践已经改变,我已经成为一名更好的开发人员 从那时起,我意识到使用Android 充气异常:无法';t解析菜单项onClick处理程序,android,android-actionbar,actionbarsherlock,Android,Android Actionbar,Actionbarsherlock,我6年前问过这个问题。与此同时,Android开发最佳实践已经改变,我已经成为一名更好的开发人员 从那时起,我意识到使用onClickXML属性是一种不好的做法,并将其从我处理的任何代码库中删除 我所有的点击处理程序现在都是在应用程序的代码中定义的,而不是在XML布局中定义的 我从不使用onClick的原因如下 onClickXML属性的值很容易出错,这将导致运行时错误 开发人员可能会重构click handler方法的名称,而没有意识到它是从布局中调用的(参见原因1) 找出实际调用的方法并不总
onClick
XML属性是一种不好的做法,并将其从我处理的任何代码库中删除
我所有的点击处理程序现在都是在应用程序的代码中定义的,而不是在XML布局中定义的
我从不使用onClick的原因如下
onClick
XML属性的值很容易出错,这将导致运行时错误onClick
将它们混合在一起,这很糟糕李>
我希望我已经说服您不要在布局中使用onClick
:)
下面是我的原始问题,它很好地说明了为什么使用onClick
是个坏主意
===
我正在用XML定义菜单项,并尝试使用API 11中添加的onClick属性。在运行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
致命异常:main
android.view.InflateException:无法解析单击处理程序时的菜单项
android.view.ContextThemeWrapper类中的OnFeedback菜单
在com.actionbarsherlock.view.MenuInflater$InflatedOnMenuItemClickListener上。(MenuInflater.java:204)
在com.actionbarsherlock.view.MenuInflater$MenuState.setItem(MenuInflater.java:410)上
在com.actionbarsherlock.view.MenuInflater$MenuState.addItem(MenuInflater.java:445)上
在com.actionbarsherlock.view.MenuInflater.parseMenu(MenuInflater.java:175)上
在com.actionbarsherlock.view.MenuInflater.inflate上(MenuInflater.java:97)
...
原因:java.lang.NoSuchMethodException:onFeedbackMenu
[接口com.actionbarsherlock.view.MenuItem]
位于java.lang.Class.GetConstructorMethod(Class.java:460)
位于java.lang.Class.getMethod(Class.java:915)
在com.actionbarsherlock.view.MenuInflater$InflatedOnMenuItemClickListener上。(MenuInflater.java:202)
... 23多
我发现ActionBar菜单项及其onClick事件也存在同样的问题。我发现我正在开发的工作站内存不足,需要重新启动。Android VM现在能够解析引用的方法名。我找到了一个适合我的解决方案。
@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);
}
通常布局中的onClick
属性具有以下方法
public void methodname(View view) {
// actions
}
在菜单项(本例中为Sherlock菜单)上,应遵循以下签名:
public boolean methodname(MenuItem item) {
// actions
}
因此,您的问题是您的方法返回了
void
而不是boolean
,在我的例子中,问题是我的菜单XML中既有onClick
,也有oncreateoptions菜单中的。我的onClick
实际上是错误的(因为它指向的是不存在的方法),但一开始我没有注意到这一点,因为我在Android 2.x下进行测试,其中onClick
不受支持且被忽略。但是,当我在4.x上测试时,我开始出现这个错误
因此,如果您计划在Android 2.x下部署,基本上不要使用onClick
。在你尝试在3.0+上运行之前,它会自动忽略你的onClick
值。在我的例子中,我的应用程序(由默认Eclipse助手启动)的android:theme=“@style/AppTheme”
块中包含android:theme=“@style/AppTheme”
在调试问题的原因时,结果发现
mMethod = c.getMethod(methodName, PARAM_TYPES);
在android.view.MenuInflater/InflatedOnMenuItemClickListener
中,调用c
不是我的Activity
类,而是一个可疑的android.view.ContextThemeWrapper
(当然不包含onClick处理程序)
因此,我删除了android:theme,一切都正常了。虽然这有点过时,但下面是例外的原因。当您在MenuInflater类中查看android API 15(4.0.3-4.0.4)的源代码时,您将看到以下方法:
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;
}
实际上,我不知道该错误是否也发生在15以下的api版本中,所以我通常使用保存版本。您的方法必须接受MenuItem作为其唯一的参数
更新,当我重新启动时,我没有意识到出现的Android虚拟机是2.3.3。但是,当我特别选择Android VM为4.0.3时,我继续得到onClick的错误。@覆盖公共布尔onCreateOptions菜单(菜单菜单菜单){getMenuInflater().inflate(R.Menu.activity_main,Menu);MenuItem item=Menu.findItem(R.id.Menu\u open);if(item==null)返回true;item.setOnMenuItemClickListener(新建MenuItem.OnMenuItemClickListener(){public boolean onMenuItemClick(MenuItem项){return(showDirectory(item));}}});返回true;}基于此线程。。建议程序员使用menu.findItem()和finditembyd()更新菜单。为此,在OnCreateOptions菜单或OnPrepareOptions菜单中维护菜单选项。。这里讨论。。我认为另一件事是幸福的
if (Build.VERSION.SDK_INT > 15)
inflater = getMenuInflater();
else
inflater = new MenuInflater(this);
public void onMenuItemClickMethod(MenuItem menuItem){
// Do stuff here
}