eowise / recyclerview-stickyheaders

DEPRECATED. Android library that integrate sticky section headers in your RecyclerView
http://eowise.github.io/recyclerview-stickyheaders
MIT License
961 stars 148 forks source link

Error IndexOutBoundsException when multiple delete item #6

Closed fjr619 closed 9 years ago

fjr619 commented 9 years ago

Firstly, thank you for your handwork, but I got issue when try to multiple delete from the bottom of item it always got IndexOutBoundsException, but if i just remove it individually it was good, and if i multiple delete from top item sometimes good sometimes got error.

java.lang.IndexOutOfBoundsException: invalid position 37. State item count is 36 at android.support.v7.widget.RecyclerView$Recycler.convertPreLayoutPositionToPostLayout(RecyclerView.java:3234) at android.support.v7.widget.RecyclerViewHelper.convertPreLayoutPositionToPostLayout(RecyclerViewHelper.java:6) at library.StickyHeadersItemDecoration.isHeader(StickyHeadersItemDecoration.java:110) at library.StickyHeadersItemDecoration.onDrawOver(StickyHeadersItemDecoration.java:58)

*note i use https://github.com/writtmeyer/recyclerviewdemo for multiple delete item

leruaa commented 9 years ago

Hello,

Thanks for raising this issue. Do you have theses exceptions with the samples or with your own app ? How do you do multiple delete ?

fjr619 commented 9 years ago

actually with the samples that you given, but i just change the data and add some function to do multiple delete.

leruaa commented 9 years ago

Ok. Can you post the code that do multiple delete (you can fork the recyclerview-stickyheaders repo) ?

fjr619 commented 9 years ago

in PersonAdapter

private SparseBooleanArray selectedItems = new SparseBooleanArray();

    @Override
    public void onBindViewHolder(final ViewHolder viewHolder, int position) {
                 ...
                viewHolder.itemView.setActivated(selectedItems.get(position,false));
        }

    public void toggleSelection(int pos) {
        if (selectedItems.get(pos, false)) {
            selectedItems.delete(pos);
        } else {
            selectedItems.put(pos, true);
        }
        notifyItemChanged(pos);
    }

    public void clearSelections() {
        selectedItems.clear();
        notifyDataSetChanged();
    }

    public int getSelectedItemCount() {
        return selectedItems.size();
    }

    public List<Integer> getSelectedItems() {
        List<Integer> items = new ArrayList<Integer>(selectedItems.size());
        for (int i = 0; i < selectedItems.size(); i++) {
            items.add(selectedItems.keyAt(i));
        }
        return items;
    }

on MainActivity i add

public class MainActivity extends Activity implements OnRemoveListener, ActionMode.Callback {

and

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.add_item) {
            countAdd++;
            Person p = new Person();
            p.setName("new name " + countAdd);
            p.setAge(30);
            personAdapter.addChild(p);

            int posAfterInsert = personDataProvider.getItems().indexOf(p);
            list.scrollToPosition(posAfterInsert);

            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onRemove(int position) {
        if (actionMode != null) {
            myToggleSelection(position);
            return;
        }

        personAdapter.removeChild(position);

    }

    @Override
    public void onLongPressRemove(int position) {
        actionMode = startActionMode(this);
        myToggleSelection(position);
    }

    private void myToggleSelection(int position) {
        personAdapter.toggleSelection(position);
        String title = getString(R.string.selected_count, personAdapter.getSelectedItemCount());
        actionMode.setTitle(title);
    }

    @Override

    public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
        MenuInflater inflater = actionMode.getMenuInflater();
        inflater.inflate(R.menu.delete_menu, menu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
        switch (menuItem.getItemId()) {
        case R.id.menu_delete:
            List<Integer> selectedItemPositions = personAdapter.getSelectedItems();
            int currPos;

            for (int i = selectedItemPositions.size() - 1; i >= 0; i--) {
                currPos = selectedItemPositions.get(i);
                Log.i("TAG", "currPos delete =" + currPos);
                personAdapter.removeChild(currPos);
            }
            actionMode.finish();
            return true;
        default:
            return false;
        }
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        this.actionMode = null;
        personAdapter.clearSelections();
    }
fjr619 commented 9 years ago

i will give you my code, because i’m still new in github so i didn’t how to do that

On Oct 29, 2014, at 4:50 PM, Aurélien notifications@github.com wrote:

Ok. Can you post the code that do multiple delete (you can fork the recyclerview-stickyheaders repo) ?

— Reply to this email directly or view it on GitHub.

leruaa commented 9 years ago

Ok, I will see that tonight.

fjr619 commented 9 years ago

you can see my project https://github.com/fjr619/RecyclerViewSticky, basically it almost same with yours, i just modify the data and the way action view on click in main activity.

thank you

fjr619 commented 9 years ago

i try use the new one 0.4.1 , that bug is still appear.

leruaa commented 9 years ago

When you remove more than one contigous item, you must call notifyItemRangeRemoved() once instead of calling notifyItemRemoved() for each items.

Please let me know if it still doesn't work.

fjr619 commented 9 years ago

i still can't do that


List<Integer> selectedItemPositions = personAdapter.getSelectedItems();
int currPos;

            for (int i = selectedItemPositions.size() - 1; i >= 0; i--) {
                currPos = selectedItemPositions.get(i);
                Log.i("TAG", "currPos delete =" + currPos);
                personDataProvider.remove(currPos);
                                personAdapter.notifyItemRemoved(currPos); --> i still got error when delete multiple item 
            }

if i want use personAdapter.notifyItemRangeRemoved, i still didn't know where i have to put that, because example i have 10 datas and i want delete index 9,5,2,1, how i have to put positionStart and itemCount

leruaa commented 9 years ago

If you change your code by :

personDataProvider.remove(1);
personDataProvider.remove(2);
personAdapter.notifyItemRangeRemoved(1, 2);
personDataProvider.remove(5);
personAdapter.notifyItemRemoved(5);
personDataProvider.remove(9);
personAdapter.notifyItemRemoved(9);

Is it working ?

fjr619 commented 9 years ago
            List<Integer> selectedItemPositions = personAdapter.getSelectedItems();
            int currPos;

//          selectedItemPositions = a(selectedItemPositions);

            for (int i = selectedItemPositions.size() - 1; i >= 0; i--) {
                currPos = selectedItemPositions.get(i);
                Log.i("TAG", "currPos delete =" + currPos);
                personDataProvider.remove(currPos);
//              personAdapter.notifyItemRemoved(currPos);
//              personAdapter.notifyItemRangeRemoved(currPos, selectedItemPositions.size());
            }

            personAdapter.notifyDataSetChanged();

personAdapter.notifyDataSetChanged(); it is help me, but still i got random bug IndexOutOfBoundsException. you can try my apt from this https://github.com/fjr619/RecyclerViewSticky/tree/master/bin

leruaa commented 9 years ago

I commited a new version of StickyHeadersItemDecoration.java.

Is it working ?

fjr619 commented 9 years ago

-still same got random IndexOutOfBoundsException when using notifyItemRemoved -error when using notifyDataSetChanged (when try to multiple delete from bottom)

fjr619 commented 9 years ago

with your last commit, it was still happened.

leruaa commented 9 years ago

I installed the apk from yout repository on my device, and I wasn't able to raise a IndexOutOfBoundsException. How can I do it ?

fjr619 commented 9 years ago

sorry for late answer, yes because i used other libs for sticky header recycler view. i will make APK with using your libs, so you can test it

fjr619 commented 9 years ago

you can try it again from https://github.com/fjr619/RecyclerViewSticky, i already update my APK

leruaa commented 9 years ago

The were a lot of refactoring and bug fixes in the latest versions.Do you still have errors ?