rakeshdas
rakeshdas

Reputation: 2543

Getting an IndexOutOfBoundsException when removing the last item from my recyclerview

I have an app where you can favorite items and an activity where you can view the items that you have favorited. In the favorites activity, you can also delete items that you have previously favorited. The favorites activity consists of a simple recyclerview to show the favorited items and of course a corresponding adapter that takes in an ArrayList of favorites to populate the recyclerview. I also have a FavoritesManager class to handle the addition and removal of favorites. The issue that I am having is that when I remove the very last favorite in my favorites list in the favorites activity, my app crashes and I get a IndexOutOfBoundsException. Here is the code that runs when the button is tapped to remove the item from the favorites:

class FavoritesListAdapter(val context: Context, val favorites: ArrayList<FavoriteSong>) : RecyclerView.Adapter<FavoritesListAdapter.FavoriteViewHolder>() {
 override fun onBindViewHolder(holder: FavoriteViewHolder?, position: Int) {
    holder?.favoriteBtn?.setOnClickListener {
        holder.favoriteBtn?.setImageResource(R.drawable.ic_favorite_border_black_24dp)
        favorites.removeAt(holder.adapterPosition)
        notifyItemRemoved(holder.adapterPosition)
        notifyDataSetChanged()
        favoritesManger.removeFavorite(context, favorites[holder.adapterPosition])
    }
}

And here is the code in my FavoritesManager class to remove the favorite from the database:

fun removeFavorite(context: Context, song: FavoriteSong) {
    val favoriteSongs = getFavorites(context)
    if (favoriteSongs != null) {
        favoriteSongs.remove(song)
        saveFavorites(context, favoriteSongs)
    }
}

I have drilled the issue down to line in my adapter that calls the FavoriteManager class to remove the favorite from the database, but I can't figure out why that's causing the issue. I can remove the last item from elsewhere in the app using the FavoritesManager class just fine, but when I run that piece of code, I get this error:

E/UncaughtException: java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
                                                                                at java.util.ArrayList.get(ArrayList.java:437)
                                                                                at com.example.favorites.adapter.FavoritesListAdapter$onBindViewHolder$1.onClick(FavoritesListAdapter.kt:37)
                                                                                at android.view.View.performClick(View.java:6294)
                                                                                at android.view.View$PerformClick.run(View.java:24770)
                                                                                at android.os.Handler.handleCallback(Handler.java:790)
                                                                                at android.os.Handler.dispatchMessage(Handler.java:99)
                                                                                at android.os.Looper.loop(Looper.java:164)
                                                                                at android.app.ActivityThread.main(ActivityThread.java:6494)
                                                                                at java.lang.reflect.Method.invoke(Native Method)
                                                                                at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
                                                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

Is there another way I could delete the last item in the list? The item that I am trying to delete is within the bounds of the list and exists in the list, so I don't understand why it isn't being removed.

Upvotes: 1

Views: 1190

Answers (2)

Ben P.
Ben P.

Reputation: 54264

In your original code, I see these two lines:

favorites.removeAt(holder.adapterPosition)
...
favoritesManger.removeFavorite(context, favorites[holder.adapterPosition])

It appears that you're removing some item from the favorites list by index, and then trying to look that same item up again as the second argument to favoritesManger.removeFavorite(). If holder.adapterPosition is the last index in the list, this will cause an IndexOutOfBoundsException. (And even when it's not the last index, you'll be removing two different items from the different collections.)

The removeAt() method returns the removed item, so you should be able to replace these two lines with:

val removed = favorites.removeAt(holder.adapterPosition)
...
favoritesManger.removeFavorite(context, removed)

Upvotes: 0

Om Infowave Developers
Om Infowave Developers

Reputation: 1565

Try updated code

 class FavoritesListAdapter(val context: Context, val favorites: ArrayList<FavoriteSong>) : RecyclerView.Adapter<FavoritesListAdapter.FavoriteViewHolder>() {
     override fun onBindViewHolder(holder: FavoriteViewHolder?, position: Int) {
        holder?.favoriteBtn?.setOnClickListener {
            holder.favoriteBtn?.setImageResource(R.drawable.ic_favorite_border_black_24dp)
            favorites.removeAt(holder.adapterPosition)
            favoritesManger.removeFavorite(context, favorites[holder.adapterPosition])
            //notifyItemRemoved(holder.adapterPosition)
            notifyDataSetChanged() 
        }
    }

Upvotes: 2

Related Questions