Android的适配器" java.lang.IndexOutOfBoundsException:无效的指数4,大小为4英寸 [英] Android Adapter "java.lang.IndexOutOfBoundsException: Invalid index 4, size is 4"
问题描述
我有删除项从的ArrayList
和同步适配器
问题。
我有一些的ArrayList
里面名为项目我的
。我从服务器dispaly里面下载一些名单。每当我点击了一些列表项我想从服务器中删除它,从当地的ArrayList和通知适配器它。问题是,当我从列表中删除一切从 RecyclerView
适配器下跌
到最高
一切正常,但是当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屋!