0

I am creating app for viewing images.So, I decided to implement multi choice deleting for pictures in grid view.I am using setMultiChoiceModeListener method.Everything woks fine, but I have one problem...I can't close contextual menu in onDestroyActionMode method.I always get such exception:

 java.lang.StackOverflowError
        at android.support.v7.internal.view.SupportActionModeWrapper$CallbackWrapper.onDestroyActionMode(SupportActionModeWrapper.java:174)
        at android.support.v7.app.AppCompatDelegateImplV7$ActionModeCallbackWrapperV7.onDestroyActionMode(AppCompatDelegateImplV7.java:1656)
        at android.support.v7.internal.app.WindowDecorActionBar$ActionModeImpl.finish(WindowDecorActionBar.java:972)
        at android.support.v7.internal.view.SupportActionModeWrapper.finish(SupportActionModeWrapper.java:78)
        at com.example.vasylpaliy.mediaview.ImageList$1.onDestroyActionMode(ImageList.java:91)
        at android.widget.AbsListView$MultiChoiceModeWrapper.onDestroyActionMode(AbsListView.java:6604)
        at com.android.internal.policy.impl.PhoneWindow$DecorView$ActionModeCallbackWrapper.onDestroyActionMode(PhoneWindow.java:3048)
        at android.support.v7.internal.view.SupportActionModeWrapper$CallbackWrapper.onDestroyActionMode(SupportActionModeWrapper.java:174)
        at android.support.v7.app.AppCompatDelegateImplV7$ActionModeCallbackWrapperV7.onDestroyActionMode(AppCompatDelegateImplV7.java:1656)
        at android.support.v7.internal.app.WindowDecorActionBar$ActionModeImpl.finish(WindowDecorActionBar.java:972)
        at android.support.v7.internal.view.SupportActionModeWrapper.finish(SupportActionModeWrapper.java:78)
        at com.example.vasylpaliy.mediaview.ImageList$1.onDestroyActionMode(ImageList.java:91)
        at android.widget.AbsListView$MultiChoiceModeWrapper.onDestroyActionMode(AbsListView.java:6604)
        at com.android.internal.policy.impl.PhoneWindow$DecorView$ActionModeCallbackWrapper.onDestroyActionMode(PhoneWindow.java:3048)
        at android.support.v7.internal.view.SupportActionModeWrapper$CallbackWrapper.onDestroyActionMode(SupportActionModeWrapper.java:174)
        at android.support.v7.app.AppCompatDelegateImplV7$ActionModeCallbackWrapperV7.onDestroyActionMode(AppCompatDelegateImplV7.java:1656)
        at android.support.v7.internal.app.WindowDecorActionBar$ActionModeImpl.finish(WindowDecorActionBar.java:972)
        at android.support.v7.internal.view.SupportActionModeWrapper.finish(SupportActionModeWrapper.java:78)
        at com.example.vasylpaliy.mediaview.ImageList$1.onDestroyActionMode(ImageList.java:91)
        at android.widget.AbsListView$MultiChoiceModeWrapper.onDestroyActionMode(AbsListView.java:6604)
        at com.android.internal.policy.impl.PhoneWindow$DecorView$ActionModeCallbackWrapper.onDestroyActionMode(PhoneWindow.java:3048)
        at android.support.v7.internal.view.SupportActionModeWrapper$CallbackWrapper.onDestroyActionMode(SupportActionModeWrapper.java:174)
        at android.support.v7.app.AppCompatDelegateImplV7$ActionModeCallbackWrapperV7.onDestroyActionMode(AppCompatDelegateImplV7.java:1656)
        at android.support.v7.internal.app.WindowDecorActionBar$ActionModeImpl.finish(WindowDecorActionBar.java:972)
        at android.support.v7.internal.view.SupportActionModeWrapper.finish(SupportActionModeWrapper.java:78)
        at com.example.vasylpaliy.mediaview.ImageList$1.onDestroyActionMode(ImageList.java:91)
        at android.widget.AbsListView$MultiChoiceModeWrapper.onDestroyActionMode(AbsListView.java:6604)
        at com.android.internal.policy.impl.PhoneWindow$DecorView$ActionModeCallbackWrapper.onDestroyActionMode(PhoneWindow.java:3048)
        at android.support.v7.internal.view.SupportActionModeWrapper$CallbackWrapper.onDestroyActionMode(SupportActionModeWrapper.java:174)
        at android.support.v7.app.AppCompatDelegateImplV7$ActionModeCallbackWrapperV7.onDestroyActionMode(AppCompatDelegateImplV7.java:1656)
        at android.support.v7.internal.app.WindowDecorActionBar$ActionModeImpl.finish(WindowDecorActionBar.java:972)
        at android.support.v7.internal.view.SupportActionModeWrapper.finish(SupportActionModeWrapper.java:78)
        at com.example.vasylpaliy.mediaview.ImageList$1.onDestroyActionMode(ImageList.java:91)
        at android.widget.AbsListView$MultiChoiceModeWrapper.onDestroyActionMode(AbsListView.java:6604)
        at com.android.internal.policy.impl.PhoneWindow$DecorView$ActionModeCallbackWrapper.onDestroyActionMode(PhoneWindow.java:3048)

Here is code:

view.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
        private boolean isDeleted;
        private ArrayList<String> imageItems;
        {
            imageItems=new ArrayList<String>();
            isDeleted=false;
        }
        @Override
        public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
            imageItems.add(imagePaths.get(position));
            mode.setTitle("Selected:" + Integer.toString(view.getCheckedItemCount()));
            imageAdapter.setCheckMark(position);
            imageAdapter.notifyDataSetChanged();
        }
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            mode.getMenuInflater().inflate(R.menu.multiple_audio, 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.multiple_audio_select_all:
                {
                    imageItems=imagePaths;
                    for(int i=0;i<imageItems.size();i++)
                        view.setItemChecked(i,true);
                    break;
                }
                case R.id.multiple_audio_deleting:
                {
                    deleteItems(imageItems);
                    isDeleted=true;
                    onDestroyActionMode(mode);
                    break;
                }
            }
            return true;
        }
        @Override
        public void onDestroyActionMode(ActionMode mode) {
            if(mode!=null)
                mode.finish();
        }
    });
nullbyte
  • 1,178
  • 8
  • 16

2 Answers2

0

finish() will cause a call of onDestroyActionMode() it will not set your mode to null.

So all you need is:

@Override
public void onDestroyActionMode(ActionMode mode) {
     // nothing here ;)
}

Also note that, if you want to finish your actionmode here:

 case R.id.multiple_audio_deleting:
     {
     deleteItems(imageItems);
     isDeleted=true;
     onDestroyActionMode(mode);
     break;
 }

change it to:

case R.id.multiple_audio_deleting:
     {
     deleteItems(imageItems);
     isDeleted=true;
     mode.finish();
     break;
 }
daemmie
  • 6,361
  • 3
  • 29
  • 45
0

I think your StackoverflowError is caused by your implementation of "onActionItemClicked()" and "onDestroyActionMode()":

With each execution of mode.finish(); in "onDestroyActionMode()", the framework will call precisely this method yet another time, so you are creating a kind of infinite loop.

According to the sample from the official documentation, especially the part about Enabling batch contextual actions in a ListView or GridView, you should change two things:

1. In your implementation of "onActionItemClicked()", call

mode.finish();

instead of "onDestroyActionMode()".

2. In your "onDestroyActionMode()", you don't need to call "finish()". You can override this method to

...make any necessary updates to the activity when the CAB is removed. By default, selected items are deselected/unchecked.

Bö macht Blau
  • 12,820
  • 5
  • 40
  • 61