Android 适配器“java.lang.IndexOutOfBoundsException:索引 4 无效,大小为 4”

2023-12-26

我在删除项目时遇到问题ArrayList并同步Adapter。 我有我的RecyclerView适配器与一些ArrayList里面叫items。我从服务器下载一些列表并在其中显示。每当我单击某些列表项时,我想将其从服务器、本地 ArrayList 中删除,并通知适配器。问题是当我删除所有内容时down to up从列表中一切都很好,但是当 f.e.我从列表中删除第一个元素,然后随机删除我单击的元素之后的一些元素。在某些情况下,应用程序会崩溃(例如,我删除第一个元素,然后删除最后一个元素)。我得到的错误是:

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

看起来它与列表大小有关,但我不知道出了什么问题?

这是我从中获取位置的函数(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 is setPopUpListener()- 看看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;
        }

    });
}

这是错误出现的地方(removeFromFavourites(position)):

  // Removing User's 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's Favourites
        removeFromUserFavouritesOnServer(recipeUniqueId, userUniqueId);

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

        // Notifying Adapter That Item Has Been Removed
        notifyItemRemoved(position);
    }
}

解决方案 - 希望这会对某人有所帮助

我已经找到了解决方案。如果有人尝试动态地从他的数组列表中删除元素并且notifyItemRemoved(position)不要发送点击位置作为内部参数onBindViewHolder(ViewHolder holder, int position)。你会遇到和我一模一样的情况。

如果列表中有 4 个显示元素,例如[0, 1, 2, 3]并尝试从列表末尾删除一切都会好的原因clicked positions将匹配完全相同positions in ArrayList。例如,如果您单击第四个元素:

position = 3- 单击列表元素时将获得的位置;myArray.remove(position)- 将删除元素index = 3 and notifyItemRemoved(position)- 将对列表进行动画处理并从显示的列表中删除已删除的元素。您将有以下列表:[0, 1, 2]。这可以。

当您想要删除随机元素时,情况会发生变化。假设我想删除第三个显示的列表元素。我点击它来删除,所以我得到:

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

在这种情况下,我将得到的 ArrayList 将如下所示:[0, 1, 3]。现在,我单击最后一个显示的元素并想删除它,这就是我将得到的:

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

但会发生什么呢?应用程序突然崩溃并出现异常:java.lang.IndexOutOfBoundsException: Invalid index 3, size is 3。这意味着我们正在尝试获取不存在位置的元素。但为什么?我从元素中获取了点击位置...这就是发生的事情:

At the beggining we had:

数组列表索引 ->[0, 1, 2, 3]

点击位置 ->[0, 1, 2, 3]

After Deleting 3rd element:

数组列表索引 ->[0, 1, 2]

点击位置 ->[0, 1, 3]

现在,当我尝试删除元素时position = 3我们不能那样做。我们没有这个立场。我们能得到的最大位置是2。这就是我们得到例外的原因。如何解决这个问题?

In onBindViewHolder(ViewHolder holder, int position)我们用了position in removeFromFavourites(position)。但我们也有我们的回报holder。如果我们使用名为的方法:getAdapterPosition()从课堂上RecyclerView.ViewHolder我们在家。

getAdapterPosition

来自开发者网站:http://developer.android.com/reference/android/support/v7/widget/RecyclerView.ViewHolder.html#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
            }

        });
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 适配器“java.lang.IndexOutOfBoundsException:索引 4 无效,大小为 4” 的相关文章

随机推荐