Android Adapter "java.lang.IndexOutOfBoundsException: invalid index 4, size 4"

I have a problem with deleting an item from ArrayListand syncing Adapter. I have an adapter RecyclerViewwith some ArrayListinside it called items. I download some list from the server and scatter inside it. Whenever I click on some elements of the list, I would like to remove it from the server, from the local ArrayList and report this to the adapter. The problem is that when I delete everything from downto upfrom the list, everything is fine, but when fe I delete the 1st element from the list, and then randomly some of the elements that it deletes after I clicked. In some cases, the application crashes (for example, I delete the 1st element, and then the last). The error I get is: fe:

java.lang.IndexOutOfBoundsException: Invalid index 4, size is 4

Looks like something with a list, but I don't know what is wrong?

Here is the function in which I got the position from ( setPopUpListener(popupMenu, position)):

// Binding New View
    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
        RecipeItem item = items.get(position);

        // Binding Recipe Image
        Picasso.with(context).load(item.getImgThumbnailLink()).into(holder.recipeItemImage);
        // Binding Recipe Title
        holder.recipeItemTitle.setText(item.getTitle());
        // Binding Recipe Subtitle
        String subtitle = "Kuchnia " + item.getKitchenType() + ", " + item.getMealType();
        holder.recipeItemSubtitle.setText(subtitle);
        // Binding Recipe Likes Count
        holder.recipeItemLikesCount.setText(Integer.toString(item.getLikeCount()));
        // Binding Recipe Add Date
        holder.recipeItemAddDate.setText(item.getAddDate());
        // Binding Recipe Options Icon
        holder.recipeItemOptionsIcon.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                PopupMenu popupMenu = new PopupMenu(context, v);
                setPopUpListener(popupMenu, position);   // Setting Popup Listener
                inflatePopupMenu(popupMenu);             // Inflating Correct Menu
                popupMenu.show();
            }

        });
        // Item Click Listener
        holder.setClickListener(new RecipeItemClickListener() {

            @Override
            public void onClick(View view, int position) {
                // taking to recipe activity
            }

        });
    }

Here setPopUpListener()- just look removeFromFavourites(position):

// Setting Popup Listener
private void setPopUpListener(PopupMenu popupMenu, final int position) {
    popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {

        @Override
        public boolean onMenuItemClick(MenuItem item) {
            switch (popupType) {
                // Add To Favourites Menu
                case 0: {
                    switch (item.getItemId()) {
                        case R.id.item_add: {
                            addToFavourites(position);
                            return true;
                        }
                    }
                }

                // Remove From Favourites Menu
                case 1: {
                    switch (item.getItemId()) {
                        case R.id.item_remove: {
                            removeFromFavourites(position);
                            return true;
                        }
                    }
                }
            }
            return false;
        }

    });
}

Here the error ( removeFromFavourites(position)) appears :

  // Removing User Favourite
private void removeFromFavourites(int position) {
    // Checking Connection Status
    if (!FormValidation.isOnline(context)) {
        showSnackbarInfo(context.getString(R.string.err_msg_connection_problem),
                R.color.snackbar_error_msg);
    } else {
        SQLiteHandler db = new SQLiteHandler(context);
        // Getting User Unique ID
        String userUniqueId = db.getUserUniqueId();
        db.close();

        RecipeItem listItem = items.get(position);
        // Getting Recipe Unique ID
        String recipeUniqueId = listItem.getUniqueId();

        // Removing From User Favourites
        removeFromUserFavouritesOnServer(recipeUniqueId, userUniqueId);

        // Removing Item From Local Array List
        items.remove(position);

        // Notifying Adapter That Item Has Been Removed
        notifyItemRemoved(position);
    }
}
+4
source share
3 answers

DECISION - HOPE THAT SOME POSSIBLE THIS WILL HELP

I found a soution for this. If someone tries to dynamically remove elements from their list of arrays and notifyItemRemoved(position)not send the click position as a parameter inside onBindViewHolder(ViewHolder holder, int position). You will face the same situation as me.

4 f.e. [0, 1, 2, 3] , . clicked positions positions in ArrayList. , 4- :

position = 3 - , ; myArray.remove(position) - index = 3 notifyItemRemoved(position) - . : [0, 1, 2]. .

, . , . , , :

position = 2myArray.remove(position)notifyItemRemoved(position)

ArrayList, , : [0, 1, 3]. , :

position = 3myArray.remove(position)notifyItemRemoved(position)

? : java.lang.IndexOutOfBoundsException: Invalid index 3, size is 3. , , . ? ... :

At the beggining we had:

- → [0, 1, 2, 3]

POSITIONS FROM CLICK → [0, 1, 2, 3]

After Deleting 3rd element:

- → [0, 1, 2]

POSITIONS FROM CLICK → [0, 1, 3]

, position = 3, . . , , 2. . ?

onBindViewHolder(ViewHolder holder, int position) position removeFromFavourites(position). holder. , : getAdapterPosition() RecyclerView.ViewHolder, .

getAdapterPosition

: http://developer.android.com/reference/android/support/v7/widget/RecyclerView.ViewHolder.html#getAdapterPosition()

, ArrayList. , , , position holder.getAdapterPosition():

// Binding New View
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        RecipeItem item = items.get(position);

        // Binding Recipe Image
        Picasso.with(context).load(item.getImgThumbnailLink()).into(holder.recipeItemImage);
        // Binding Recipe Title
        holder.recipeItemTitle.setText(item.getTitle());
        // Binding Recipe Subtitle
        String subtitle = "Kuchnia " + item.getKitchenType() + ", " + item.getMealType();
        holder.recipeItemSubtitle.setText(subtitle);
        // Binding Recipe Likes Count
        holder.recipeItemLikesCount.setText(Integer.toString(item.getLikeCount()));
        // Binding Recipe Add Date
        holder.recipeItemAddDate.setText(item.getAddDate());
        // Binding Recipe Options Icon
        holder.recipeItemOptionsIcon.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                PopupMenu popupMenu = new PopupMenu(context, v);
                setPopUpListener(popupMenu, holder.getAdapterPosition());   // Setting Popup Listener
                inflatePopupMenu(popupMenu);             // Inflating Correct Menu
                popupMenu.show();
            }

        });
        // Item Click Listener
        holder.setClickListener(new RecipeItemClickListener() {

            @Override
            public void onClick(View view, int position) {
                // taking to recipe activity
            }

        });
    }
+14

notifyItemRangeChanged (position, getItemCount()); notifyItemRemoved (); , .

+3

, .

:

  • In the case of an add / remove operation, do this with the main array (e.g. ArrayList), which is passed to the adapter
  • Never initialize the main array (which is passed to the adapter) to null, it will lose the link to the adapter
  • After adding / removing only a call adapter.notifyDataSetChanged();for the adapter
0
source

Source: https://habr.com/ru/post/1621655/


All Articles