Android的适配器" java.lang.IndexOutOfBoundsException:无效的指数4,大小为4英寸 [英] Android Adapter "java.lang.IndexOutOfBoundsException: Invalid index 4, size is 4"

查看:694
本文介绍了Android的适配器" java.lang.IndexOutOfBoundsException:无效的指数4,大小为4英寸的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有删除项从的ArrayList 和同步适配器问题。
我有一些的ArrayList 里面名为项目我的 RecyclerView 适配器。我从服务器dispaly里面下载一些名单。每当我点击了一些列表项我想从服务器中删除它,从当地的ArrayList和通知适配器它。问题是,当我从列表中删除一切从下跌最高一切正常,但是当F.E.我从列表中删除1个元素,然后随意一些它的人,我点击后删除元素的元素。在某些情况下,应用程序崩溃指标(如我删除,然后1个元素的最后一个)。我得到的错误是f.e:

java.lang.IndexOutOfBoundsException:无效的指数4,大小为4

看起来像它的东西与列表大小,但我不知道什么是错?

下面是我得到的位置从( setPopUpListener(POPUPMENU,位置))的功能:

  //绑定新视角
    @覆盖
    公共无效onBindViewHolder(ViewHolder持有人,最终诠释位置){
        RecipeItem项目= items.get(位置);        //绑定食谱图片
        Picasso.with(上下文).load(item.getImgThumbnailLink())到(holder.recipeItemImage)。
        //绑定配方标题
        holder.recipeItemTitle.setText(item.getTitle());
        //绑定配方字幕
        字符串字幕=Kuchnia+ item.getKitchenType()+,+ item.getMealType();
        holder.recipeItemSubtitle.setText(字幕);
        //绑定配方喜欢伯爵
        holder.recipeItemLikesCount.setText(Integer.toString(item.getLikeCount()));
        //绑定配方添加日期
        holder.recipeItemAddDate.setText(item.getAddDate());
        //绑定配方选项图标
        holder.recipeItemOptionsIcon.setOnClickListener(新View.OnClickListener(){            @覆盖
            公共无效的onClick(视图v){
                PopupMenu的弹出菜单=新的PopupMenu(背景下,V);
                setPopUpListener(POPUPMENU,位置); //设置弹出式监听器
                inflatePopupMenu(弹出菜单); //充气正确的菜单
                popupMenu.show();
            }        });
        //项目点击监听器
        holder.setClickListener(新RecipeItemClickListener(){            @覆盖
            公共无效的onClick(查看视图,INT位置){
                //考虑到配方活动
            }        });
    }

下面是 setPopUpListener() - 只要看看 removeFromFavourites(位置)

  //设置弹出式监听器
私人无效setPopUpListener(PopupMenu的弹出菜单,最终诠释位置){
    popupMenu.setOnMenuItemClickListener(新PopupMenu.OnMenuItemClickListener(){        @覆盖
        公共布尔onMenuItemClick(菜单项项){
            开关(popupType){
                //添加至收藏夹菜单
                情况下0:{
                    开关(item.getItemId()){
                        案例R.id.item_add:{
                            addToFavourites(位置);
                            返回true;
                        }
                    }
                }                //从收藏夹菜单中删除
                情况1: {
                    开关(item.getItemId()){
                        案例R.id.item_remove:{
                            removeFromFavourites(位置);
                            返回true;
                        }
                    }
                }
            }
            返回false;
        }    });
}

下面是出现在错误的位置( removeFromFavourites(位置)

  //删除用户的最爱
私人无效removeFromFavourites(INT位置){
    //检查连接状态
    如果(!FormValidation.isOnline(上下文)){
        showSnackbarInfo(context.getString(R.string.err_msg_connection_problem)
                R.color.snackbar_error_msg);
    }其他{
        SQLiteHandler DB =新SQLiteHandler(背景);
        //获取用户的唯一ID
        串userUniqueId = db.getUserUniqueId();
        db.close();        RecipeItem的listItem = items.get(位置);
        //获取配方的唯一ID
        串recipeUniqueId = listItem.getUniqueId();        //删除从用户的收藏
        removeFromUserFavouritesOnServer(recipeUniqueId,userUniqueId);        //删除项目从本地数组列表
        items.remove(位置);        //通知适配器项目已被删除
        notifyItemRemoved(位置);
    }
}


解决方案

解决方案 - 希望这将帮助别人

我已经找到了这个soution。如果有人将曾经尝试动态地从他的数组列表和 notifyItemRemoved(位置)不送作为内 onBindViewHolder参数点击的位置(ViewHolder持有人删除元素,INT位置)。你会用完全相同的情况下满足像我一样。

如果您有4个在列表中显示F.E.元素 [0,1,2,3] ,并尝试从列表中一切的结束除去将被罚款的原因点击位置将匹配完全相同的的ArrayList中位置。例如,如果您单击第4单元:

位置= 3 - 位置列表元素上点击后你会得到; myArray.remove(位置) - 将删除元素和指数= 3 notifyItemRemoved(位置) - 将动画列表中,并从显示的列表中删除已删除的元素。你将有以下列表: [0,1,2] 。这是很好。

当您想删除随机元素形势的变化。比方说,我要删除第3显示的列表元素。我点击它删除,所以我得到:

位置= 2 - > myArray.remove(位置) - > notifyItemRemoved(位置)

在这种情况下,我将获得ArrayList的将是这样的: [0,1,3] 。在我现在点击最后dispalyed元素上,并想将其删除,这就是我将获得:

位置= 3 - > myArray.remove(位置) - > notifyItemRemoved(位置)

但是,会发生什么?应用程序突然崩溃例外: java.lang.IndexOutOfBoundsException:无效指数3,大小为3 。这意味着我们试图在不存在的位置来获得元件。但为什么?我从我的元素点击位置......这是发生了什么:

在我们有beggining:

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

持仓量由点击 - > [0,1,2,3]

删除第三元素后:

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

持仓量由点击 - > [0,1,3]

当我尝试在位置删除元素

现在= 3 ,我们不能这样做。我们没有那个位置。最大位置,我们可以得到的是 2 。这就是为什么我们得到的异常。如何管理这个问题?

onBindViewHolder(ViewHolder持有人,INT位置)我们使用位置
removeFromFavourites(位置)。但我们也有我们的返回。如果我们使用的方法叫做: getAdapterPosition()从类 RecyclerView.ViewHolder 我们在家里

getAdapterPosition

从开发者网站:<一href=\"http://developer.android.com/reference/android/support/v7/widget/RecyclerView.ViewHolder.html#getAdapterPosition()\" rel=\"nofollow\">http://developer.android.com/reference/android/support/v7/widget/RecyclerView.ViewHolder.html#getAdapterPosition()

这总是会的ArrayList 返回指数完全相同。所以summaring所有我们所要做的就是不断变化的位置参数与 holder.getAdapterView()

  //绑定新视角
    @覆盖
    公共无效onBindViewHolder(ViewHolder持有人,INT位置){
        RecipeItem项目= items.get(位置);        //绑定食谱图片
        Picasso.with(上下文).load(item.getImgThumbnailLink())到(holder.recipeItemImage)。
        //绑定配方标题
        holder.recipeItemTitle.setText(item.getTitle());
        //绑定配方字幕
        字符串字幕=Kuchnia+ item.getKitchenType()+,+ item.getMealType();
        holder.recipeItemSubtitle.setText(字幕);
        //绑定配方喜欢伯爵
        holder.recipeItemLikesCount.setText(Integer.toString(item.getLikeCount()));
        //绑定配方添加日期
        holder.recipeItemAddDate.setText(item.getAddDate());
        //绑定配方选项图标
        holder.recipeItemOptionsIcon.setOnClickListener(新View.OnClickListener(){            @覆盖
            公共无效的onClick(视图v){
                PopupMenu的弹出菜单=新的PopupMenu(背景下,V);
                setPopUpListener(PopupMenu的,holder.getAdapterPosition()); //设置弹出式监听器
                inflatePopupMenu(弹出菜单); //充气正确的菜单
                popupMenu.show();
            }        });
        //项目点击监听器
        holder.setClickListener(新RecipeItemClickListener(){            @覆盖
            公共无效的onClick(查看视图,INT位置){
                //考虑到配方活动
            }        });
    }

I have problem with deleting item's from ArrayList and synchronising Adapter. I have my RecyclerView adapter with some ArrayList inside it called items. I download some list from the server and dispaly inside it. Whenever I click on some of list items I would like to delete it from server, from local ArrayList and notify the adapter about it. The problem is that when I delete everything from down to up from the list everything is ok, but when f.e. I delete 1st element from the list and then randomly some of the elements it deletes element after the one I clicked. In some cases the app crashes (f.e. I delete 1st element then the last one). The error I get is f.e.:

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

Look like it's something with list size but i don't know what is wrong?

Here is the function where I got 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 is setPopUpListener() - just look at 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 is where the error appears (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);
    }
}

解决方案

SOLUTION - HOPE THIS WILL HELP SOMEBODY

I have found the soution for this. If somebody will ever try to dynamicly remove elements from his array list and notifyItemRemoved(position) do not send clicked position as a parameter inside onBindViewHolder(ViewHolder holder, int position). You will meet with exactly the same situation as I did.

If you have 4 displayed elements in a list f.e. [0, 1, 2, 3] and try to remove from the end of the list everything will be fine cause clicked positions will match exactly the same positions in ArrayList. For example if you click 4th element:

position = 3 - position you will get when clicked on list element; myArray.remove(position) - will remove element with index = 3 and notifyItemRemoved(position) - will animate the list and remove deleted element from the displayed list. You are going to have following list: [0, 1, 2]. This is fine.

Situation changes when you want to delete random element. Let's say I want to delete 3rd displayed list element. I click on it to delete so i get:

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

In this case the ArrayList I am going to get will be like this: [0, 1, 3]. In I now click on the last dispalyed element and would like to delete it that's what I will get:

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

But what happens? App suddenly crashes with exception: java.lang.IndexOutOfBoundsException: Invalid index 3, size is 3. It means that we are trying to get element at the position that does not exist. But why? I got my clicked position from element... This is what happened:

At the beggining we had:

ARRAY LIST INDEXES -> [0, 1, 2, 3]

POSITIONS FROM CLICK -> [0, 1, 2, 3]

After Deleting 3rd element:

ARRAY LIST INDEXES -> [0, 1, 2]

POSITIONS FROM CLICK -> [0, 1, 3]

Now when I try to delete element at position = 3 we can't do that. We do not have that position. The max position we can get is 2. Thats why we get the exception. How to manage that problem?

In onBindViewHolder(ViewHolder holder, int position) we used position in removeFromFavourites(position). But we also have our returned holder. If we use method called: getAdapterPosition() from class RecyclerView.ViewHolder we are at home.

getAdapterPosition

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

This will always return index identical to that in ArrayList. So summaring all we had to do was changing position parameter with holder.getAdapterView():

// 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
            }

        });
    }

这篇关于Android的适配器&QUOT; java.lang.IndexOutOfBoundsException:无效的指数4,大小为4英寸的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆