【发布时间】:2020-04-02 13:04:46
【问题描述】:
我正在以这种方式将视图添加到FrameLayout
frameLayout.post(new Runnable() {
@Override
public void run() {
for (int i = 0; i < adapter.getCount(); i++) {
View view = adapter.getView(i, null, frameLayout);
frameLayout.addView(view);
registerForContextMenu(view);
}
}
});
在onCreateContextMenu 中,我将选择的视图保存在一个变量中
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.fragment_page_lesson_menu, menu);
selectedView = v; // Saved view
}
但是在onContextItemSelected 中,当我尝试访问它时,它是null
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.remove:
db.delete(selectedView.getID()); // Error selectedView is null
return true;
default:
return super.onContextItemSelected(item);
}
}
所有这些代码都在同一个 Fragment 类中。
public class MyFragment {
private View selectedView;
// Code...
}
附加信息。
-
selectedView不应为空,因为 onContextItemSelected 是 在 onCreateContextMenu 之后调用,对吗? - 如果
selectedView被声明为static,则没有NullPointerException一切都很好。 -
frameLayout只是在onContextItemSelected结果为空 (frameLayout.getChildCount()) 时 不是
【问题讨论】:
-
目前尚不清楚为什么要将
Adapter中的一堆Views 堆叠在FrameLayout中,但您似乎有多个Fragment实例主动,有意或无意。为每个活动的Fragment调用onContextItemSelected()方法,直到返回true以指示选择已被处理。如果您一次只应该运行一个MyFragment实例,那么您应该找出其他实例的来源。否则,将需要一些繁琐的工作来确保上下文菜单适用于给定的实例和View。 -
@MikeM。非常感谢您的评论。我确实使用了
FrameLayout,因为我正在制作日历并且使用ListView我无法很好地定位视图(view.setY不起作用)。是的,Fragment有多个实例,因为我使用的是ViewPager。所以这就是问题所在。将selectedViewstatic作为解决方案怎么样? -
是的,大多数情况下这可能会起作用,但它有点老套,静态的
View引用是一个普遍的禁忌。可能一种更好但不太乏味的方法是首先在onContextItemSelected()中对selectedView进行空检查——如果它为空则返回false——然后在onContextMenuClosed()中设置selectedView = null;。有了这个,你在onCreateContextMenu()中设置selectedView = v;,只有当前的Fragment应该有一个非空的selectedView。 -
@MikeM。它有效,谢谢。这就是我一直在寻找的
-
哎呀,我的建议搞错了。我注意到你覆盖了
onOptionsMenuClosed()而不是onContextMenuClosed(),正如我所建议的那样。我刚刚意识到Fragment没有onContextMenuClosed()方法,所以显然你不能这样做,而且你的代码中仍然存在一个微妙的错误。完全摆脱onOptionsMenuClosed()方法,使用后将selectedView = null;移动到onContextItemSelected()。你真的应该在case和default中都这样做,或者将其重构为最后只有一个return语句,然后在此之前执行。
标签: java android android-fragments nullpointerexception