在回收站视图片段中执行上下文动作模式的问题

我从一堆教程中一起入侵了我的第一个应用程序。 在他们中的一个的帮助下,我在主要活动使用的片段内实现了一个RecyclerView。 现在我发现了另一个教程 ,我想用它来实现与上下文动作模式的多选。 最大的问题是,教程没有使用片段。 我试图重写代码以适应片段。 我现在在一个点,我没有在Android Studio中的任何错误,并运行应用程序,但是当我真的做LongClickselect一个项目,它崩溃与NullPointerException:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.view.ActionMode.setTitle(java.lang.CharSequence)' on a null object reference

我完全失去了为什么会发生这种情况,以及一般的多选题。

我认为每个涉及的类的相关部分是:

Adapter.java:

 public class Adapter extends SelectableAdapter<Adapter.ViewHolder> { private ArrayList<Meal> items = new ArrayList<>(); private Context context; private ViewHolder.ClickListener clickListener; public Adapter(ViewHolder.ClickListener clickListener) { super(); this.clickListener = clickListener; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_today_items, parent, false); return new ViewHolder(v, clickListener); } @Override public void onBindViewHolder(final ViewHolder holder, int position) { Meal currentMeal = items.get(position); holder.meal_typeicon.setImageResource(currentMeal.getBadgeIcon()); holder.meal_price.setText(currentMeal.getPriceOutput()); holder.meal_name.setText(isSelected(position) ? "SELECTED" : "NOT SELECTED"); } public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { @SuppressWarnings("unused") private static final String TAG = ViewHolder.class.getSimpleName(); private RelativeLayout meal_item; private ClickListener listener; private TextView meal_name; private TextView meal_price; private TextView meal_contents; private TextView meal_contents_spelledout; private ImageView meal_typeicon; public ViewHolder(View itemView, ClickListener listener) { super(itemView); meal_item = (RelativeLayout) itemView.findViewById(R.id.meal_item); this.listener = listener; itemView.setOnClickListener(this); itemView.setOnLongClickListener(this); meal_name = (TextView) itemView.findViewById(R.id.meal_name); meal_price = (TextView) itemView.findViewById(R.id.meal_price); meal_contents = (TextView) itemView.findViewById(R.id.meal_contents); meal_contents_spelledout = (TextView) itemView.findViewById(R.id.meal_contents_spelledout); meal_typeicon = (ImageView) itemView.findViewById(R.id.meal_typeicon); } @Override public void onClick(View v) { if (listener != null) { listener.onItemClicked(getAdapterPosition()); } } @Override public boolean onLongClick(View v) { if (listener != null) { return listener.onItemLongClicked(getAdapterPosition()); } return false; } public interface ClickListener { void onItemClicked(int position); boolean onItemLongClicked(int position); } } @Override public int getItemCount() { return items.size(); } public void setMealList(ArrayList<Meal> listMeals) { this.items = listMeals; notifyDataSetChanged(); notifyItemRangeChanged(0, listMeals.size()); } } 

SelectableAdapter.java:

 public abstract class SelectableAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> { @SuppressWarnings("unused") private static final String TAG = SelectableAdapter.class.getSimpleName(); private SparseBooleanArray selectedItems; public SelectableAdapter() { selectedItems = new SparseBooleanArray(); } /** * Indicates if the item at position position is selected * @param position Position of the item to check * @return true if the item is selected, false otherwise */ public boolean isSelected(int position) { return getSelectedItems().contains(position); } /** * Toggle the selection status of the item at a given position * @param position Position of the item to toggle the selection status for */ public void toggleSelection(int position) { if (selectedItems.get(position, false)) { selectedItems.delete(position); } else { selectedItems.put(position, true); } notifyItemChanged(position); } /** * Clear the selection status for all items */ public void clearSelection() { List<Integer> selection = getSelectedItems(); selectedItems.clear(); for (Integer i : selection) { notifyItemChanged(i); } } /** * Count the selected items * @return Selected items count */ public int getSelectedItemCount() { return selectedItems.size(); } /** * Indicates the list of selected items * @return List of selected items ids */ public List<Integer> getSelectedItems() { List<Integer> items = new ArrayList<>(selectedItems.size()); for (int i = 0; i < selectedItems.size(); ++i) { items.add(selectedItems.keyAt(i)); } return items; } } 

FragmentToday.java:

 public class FragmentToday extends Fragment implements Adapter.ViewHolder.ClickListener{ private RequestQueue requestQueue; public ArrayList<Meal> listMeals = new ArrayList<>(); private TextView textVolleyError; private MealSorter mSorter = new MealSorter(); private Adapter adapter; private ActionModeCallback actionModeCallback = new ActionModeCallback(); private ActionMode actionMode; public static FragmentToday newInstance() { return new FragmentToday(); } public FragmentToday() { } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); VolleySingleton volleySingleton = VolleySingleton.getInstance(); requestQueue = volleySingleton.getRequestQueue(); sendJsonRequest(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_today, container, false); textVolleyError = (TextView) view.findViewById(R.id.textVolleyError); adapter = new Adapter(this); RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view); recyclerView.setAdapter(adapter); recyclerView.setItemAnimator(new DefaultItemAnimator()); recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); sendJsonRequest(); return view; } @Override public void onItemClicked(int position) { if (actionMode != null) { toggleSelection(position); } } @Override public boolean onItemLongClicked(int position) { if (actionMode != null) { ((AppCompatActivity) getActivity()).startSupportActionMode(actionModeCallback); } toggleSelection(position); return true; } private void toggleSelection(int position) { adapter.toggleSelection(position); int count = adapter.getSelectedItemCount(); if (count == 0) { actionMode.finish(); } else { actionMode.setTitle(String.valueOf(count)); actionMode.invalidate(); } } private class ActionModeCallback implements ActionMode.Callback { @SuppressWarnings("unused") private final String TAG = ActionModeCallback.class.getSimpleName(); @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { mode.getMenuInflater().inflate (R.menu.menu_cam, menu); return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.favorite: // TODO: actually remove items Log.d(TAG, "menu_remove"); mode.finish(); return true; default: return false; } } @Override public void onDestroyActionMode(ActionMode mode) { adapter.clearSelection(); actionMode = null; } } } 

Solutions Collecting From Web of "在回收站视图片段中执行上下文动作模式的问题"

这个问题似乎来自于FragmentToday.java类的onItemLongClicked方法。 应该是:

 @Override public boolean onItemLongClicked(int position) { if (actionMode == null) { actionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(actionModeCallback); } toggleSelection(position); return true; } 

代替:

 @Override public boolean onItemLongClicked(int position) { if (actionMode != null) { ((AppCompatActivity) getActivity()).startSupportActionMode(actionModeCallback); } toggleSelection(position); return true; }