片段上下文菜单通知适配器

Fragment Context Menu Notify Adapter

我在 Fragment 中有一个 ListView。我一直在尝试设置功能 ContextMenu 来删除和编辑条目。只需传递 saveAdapter.notifyDataSetChanged(); returns null。传递 ArrayAdapter<LiftSave> saveAdapter = new SaveListAdapter(); 会产生一条消息:

java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes.

我非常感谢任何有关解析适配器的见解,and/or任何关于设置编辑选项的最佳实践的建议。也许启动自定义 AlertDialog?提前致谢。

片段:

   public static class FragmentS extends Fragment {

    private ListView saveListView;
    private List<LiftSave> LiftSaves = new ArrayList<LiftSave>();
    private static final int EDIT = 0, DELETE = 1;

    int longClickedItemIndex;
    DatabaseHandler dbHandler;
    ArrayAdapter<LiftSave> saveAdapter;


    public FragmentS() {

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.listview_s,
                container, false);
        saveListView = (ListView) rootView.findViewById(R.id.saveListView);
        registerForContextMenu(saveListView);
        DatabaseHandler dbHandler;
        dbHandler = new DatabaseHandler (getActivity().getApplicationContext());
        if (dbHandler.getLiftSavesCount() != 0)
            LiftSaves.addAll(dbHandler.getAllLiftSaves());

        populateList();

        saveListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                longClickedItemIndex = position;
                return false;
            }
        });
        return rootView;
    }

    private void populateList() {
        ArrayAdapter<LiftSave> saveAdapter = new SaveListAdapter();
        saveListView.setAdapter(saveAdapter);
    }

    public class SaveListAdapter extends ArrayAdapter<LiftSave> {
            public SaveListAdapter() {
                super(getActivity(), R.layout.listview_item, LiftSaves);
            }

            @Override
            public View getView(int position, View view, ViewGroup parent) {
                if (view == null)
                    view = getActivity().getLayoutInflater().inflate(R.layout.listview_item, parent, false);

                LiftSave currentLiftSave = LiftSaves.get(position);

                TextView liftName = (TextView) view.findViewById(R.id.liftName);
                liftName.setText(currentLiftSave.getLiftName());
                TextView maxValue = (TextView) view.findViewById(R.id.maxValue);
                maxValue.setText(currentLiftSave.getMaxValue());
                TextView weightAndReps = (TextView) view.findViewById(R.id.weightAndReps);
                weightAndReps.setText(currentLiftSave.getRepsAndWeight());
                TextView liftNotes = (TextView) view.findViewById(R.id.liftNotes);
                liftNotes.setText(currentLiftSave.getLiftNotes());
                TextView date = (TextView) view.findViewById(R.id.todayDate);
                date.setText(currentLiftSave.getTodayDate());

                return view;
            }

    }
    public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, view, menuInfo);

        menu.setHeaderIcon(R.drawable.pencil_icon);
        menu.setHeaderTitle("Save Options");
        menu.add(Menu.NONE, EDIT, menu.NONE, "Edit Save");
        menu.add(Menu.NONE, DELETE, menu.NONE, "Delete Save");
    }

    public boolean onContextItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case EDIT:
                // TODO: Add save edit code
                break;
            case DELETE:
                dbHandler = new DatabaseHandler (getActivity().getApplicationContext());
                dbHandler.deleteLiftSave(LiftSaves.get(longClickedItemIndex));
                LiftSaves.remove(longClickedItemIndex);
                saveAdapter.notifyDataSetChanged();
                break;
        }

        return super.onContextItemSelected(item);
    }
}

XML:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".TabbedActivity$FragmentS"
android:background="@android:color/holo_blue_dark">

<LinearLayout
android:id="@+id/tabSaveList"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:text="Saved Maxes"
    android:id="@+id/textView"
    android:layout_gravity="center"
    android:layout_marginTop="10dp"
    android:textColor="#fffaf4a1"
    android:textStyle="bold" />

<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/saveListView" />


</LinearLayout>
</RelativeLayout>

int longClickedItemIndex; 更改为 LiftSave longClickedItemLiftSave;

然后在长按监听器中捕获该值作为 longClickedItemLiftSave:

        saveListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            longClickedItemLiftSave = (LiftSave) parent.getItemAtPosition(position);
            return false;
        }
    });

然后在您的菜单处理中调用 ArrayAdapter#remove(T),这将为您调用 notifyDataSetChanged

        case DELETE:
            dbHandler = new DatabaseHandler (getActivity().getApplicationContext());
            dbHandler.deleteLiftSave(longClickedItemLiftSave);
            saveAdapter.remove(longClickedItemLiftSave);
            break;

最后,更改您的 populateList,使其仅使用 saveAdapter 的片段字段而不是此方法的局部变量。

private void populateList() {
    saveAdapter = new SaveListAdapter();
    saveListView.setAdapter(saveAdapter);
}