OnDestroyActionMode() 中断了 onActionItemClicked()

OnDestroyActionMode() interrupted onActionItemClicked()

我有一个名为 delete 的操作项,它获取我创建的 ArrayList 并删除所有选中的联系人(基于我在 class 联系人中的布尔变量)。

当我点击删除时一切都很好,它是一个项目,但如果它超过 6 个项目,onDestroyActionMode 方法会中断我的 onActionItemClicked 方法并且一些项目不会被删除。我该如何解决?

这是我的代码:

import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.List;

public class ContactViewAdapter extends RecyclerView.Adapter<ContactViewAdapter.ContactViewHolder> {

private static final String TAG = "AKS";

private AppCompatActivity mActivity;
private List<Contact> contactList;
public ActionMode mActionMode = null;
public ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.action_mode_menu, 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.action_mode_delete:
                for (int i = 0; i < contactList.size(); i++) {
                    Log.d(TAG, "size " + String.valueOf(contactList.size()));
                    if (contactList.get(i).isSelected) {
                        contactList.remove(i);
                    }
                }
                notifyDataSetChanged();

                mode.finish();
                return true;
            default:
                return false;
        }
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        for (Contact c : contactList) {
            c.isSelected = false;
            Log.d(TAG, "onDestroyActionMode");
        }
        mActionMode.finish();
        mActionMode = null;
        notifyDataSetChanged();
    }
};

public class ContactViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {

    public TextView contactName;
    public TextView contactMoneyOwed;
    public ImageView contactPhoto;
    public CheckBox isCheckedBox;

    public ContactViewHolder(View v) {
        super(v);
        contactName = (TextView) itemView.findViewById(R.id.contact_name);
        contactMoneyOwed = (TextView) itemView.findViewById(R.id.contact_money_owed);
        contactPhoto = (ImageView) itemView.findViewById(R.id.contact_photo);
        isCheckedBox = (CheckBox) itemView.findViewById(R.id.listItemCheckBox);
        v.setOnClickListener(this);
        v.setOnLongClickListener(this);
    }

    @Override
    public void onClick(View v) {
        boolean everythingIsUnchecked = true;
        for (Contact c : contactList) {
            if (c.isSelected) {
                everythingIsUnchecked = false;
            }
        }
        if (!everythingIsUnchecked) {
            isCheckedBox.setChecked(!isCheckedBox.isChecked());
        } else {
            Toast.makeText(mActivity.getApplicationContext(), "Coming soon!", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public boolean onLongClick(View v) {
        isCheckedBox.setChecked(true);
        return true;
    }
}

public ContactViewAdapter(List<Contact> contactList, AppCompatActivity activity) {
    this.contactList = contactList;
    this.mActivity = activity;
}

@Override
public ContactViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
    return new ContactViewHolder(v);
}

@Override
public void onBindViewHolder(final ContactViewHolder contactViewHolder, final int position) {
    contactViewHolder.contactName.setText(contactList.get(position).name);
    contactViewHolder.contactMoneyOwed.setText(contactList.get(position).moneyOwed);
    contactViewHolder.contactPhoto.setImageResource(contactList.get(position).photoID);
    contactViewHolder.contactPhoto.setOnTouchListener(null);
    contactViewHolder.contactPhoto.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                contactViewHolder.isCheckedBox.setChecked(true);
            }
            return true;
        }
    });
    contactViewHolder.isCheckedBox.setOnCheckedChangeListener(null);
    contactViewHolder.isCheckedBox.setChecked(contactList.get(position).isSelected);

    if (contactViewHolder.isCheckedBox.isChecked()) {
        contactViewHolder.contactPhoto.setVisibility(View.GONE);
        contactViewHolder.isCheckedBox.setVisibility(View.VISIBLE);
    } else {
        contactViewHolder.isCheckedBox.setVisibility(View.GONE);
        contactViewHolder.contactPhoto.setVisibility(View.VISIBLE);
    }

    contactViewHolder.isCheckedBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            Log.d(TAG, String.valueOf(position));
            contactList.get(position).isSelected = isChecked;
            boolean everythingIsUnchecked = true;
            for (Contact c : contactList) {
                if (c.isSelected) {
                    everythingIsUnchecked = false;
                }
            }
            if (mActionMode == null) {
                mActionMode = mActivity.startActionMode(mActionModeCallback);
            } else if (everythingIsUnchecked) {
                mActionMode.finish();
                mActionMode = null;
            }
            if (isChecked) {
                contactViewHolder.contactPhoto.setVisibility(View.GONE);
                contactViewHolder.isCheckedBox.setVisibility(View.VISIBLE);
            } else {
                contactViewHolder.isCheckedBox.setVisibility(View.GONE);
                contactViewHolder.contactPhoto.setVisibility(View.VISIBLE);
            }
        }
    });
}

@Override
public int getItemCount() {
    return contactList.size();
    }

}

这是我从日志中得到的:

10-03 19:47:23.181 1962-1962/com.example.andreassavva.expensemanager D/AKS: 0
10-03 19:47:23.413 1962-1962/com.example.andreassavva.expensemanager D/AKS: 1
10-03 19:47:23.789 1962-1962/com.example.andreassavva.expensemanager D/AKS: 2
10-03 19:47:24.067 1962-1962/com.example.andreassavva.expensemanager D/AKS: 3
10-03 19:47:24.453 1962-1962/com.example.andreassavva.expensemanager D/AKS: 4
10-03 19:47:25.115 1962-1962/com.example.andreassavva.expensemanager D/AKS: 5
10-03 19:47:26.350 1962-1962/com.example.andreassavva.expensemanager D/AKS: 6
10-03 19:47:26.734 1962-1962/com.example.andreassavva.expensemanager D/AKS: 7
10-03 19:47:27.046 1962-1962/com.example.andreassavva.expensemanager D/AKS: 8
10-03 19:47:27.468 1962-1962/com.example.andreassavva.expensemanager D/AKS: 9
10-03 19:47:27.812 1962-1962/com.example.andreassavva.expensemanager D/AKS: 10
10-03 19:47:29.658 1962-1962/com.example.andreassavva.expensemanager D/AKS: size 11
10-03 19:47:29.658 1962-1962/com.example.andreassavva.expensemanager D/AKS: size 10
10-03 19:47:29.658 1962-1962/com.example.andreassavva.expensemanager D/AKS: size 9
10-03 19:47:29.658 1962-1962/com.example.andreassavva.expensemanager D/AKS: size 8
10-03 19:47:29.658 1962-1962/com.example.andreassavva.expensemanager D/AKS: size 7
10-03 19:47:29.658 1962-1962/com.example.andreassavva.expensemanager D/AKS: size 6
10-03 19:47:29.659 1962-1962/com.example.andreassavva.expensemanager D/AKS: onDestroyActionMode
10-03 19:47:29.659 1962-1962/com.example.andreassavva.expensemanager D/AKS: onDestroyActionMode
10-03 19:47:29.659 1962-1962/com.example.andreassavva.expensemanager D/AKS: onDestroyActionMode
10-03 19:47:29.659 1962-1962/com.example.andreassavva.expensemanager D/AKS: onDestroyActionMode
10-03 19:47:29.659 1962-1962/com.example.andreassavva.expensemanager D/AKS: onDestroyActionMode

ActionMode.finish() 呼叫 onDestroyActionMode()。因此,从 onDestroyActionMode() 实现中删除对 finish() 的调用。新实现变为:

@Override
public void onDestroyActionMode(ActionMode mode) {
    for (Contact c : contactList) {
        c.isSelected = false;
        Log.d(TAG, "onDestroyActionMode");
    }
    //mActionMode.finish();
    mActionMode = null;
    notifyDataSetChanged();
}

由于您在 onDestroyActionMode() 中调用 notifyDataSetChanged(),请从 onActionItemClicked() 的实现中删除该调用。新的 onActionItemClicked() 实现变为:

编辑:

 @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {

        switch (item.getItemId()) {
            case R.id.action_mode_delete:
            Iterator<Contact> contactIterator = contactList.iterator();
                while(contactIterator.hasNext()) {
                  Contact contact = contactIterator.next();
                  if (contact.isSelected) {
                     contactIterator.remove();
                  }
                }
                //notifyDataSetChanged();

                mode.finish();// This calls 'onDestroyActionMode()'
                // and it will notify the data set change.
                return true;
            default:
                return false;
        }
    }

想通了。我的 for 循环很烂。我需要将其更改为

for (int i = contactList.size() - 1; i >= 0; i--) {
                        if (contactList.get(i).isSelected()) {
                            contactList.remove(i);
                        }
                    }

相反。感谢您的帮助!