gpt4 book ai didi

java - 适配器上的 notifydataSetChanged 将更新新项目,但不会更新现有项目

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:17:16 28 4
gpt4 key购买 nike

我找不到与我的确切问题具体相关的内容,请继续阅读以找出具体内容。

我非常小心地确保在我的代码中的任何地方,我都设置为只调用适配器上的 notifyDataSetChanged,我初始化 itemList 一次,然后将其传递给适配器,并且不重新初始化它曾经。

它就像一个魅力, ListView 会自行更新,但仅限于新项目。

对于现有项目,ListView 将不会正确更新。

例如,如果我有一个显示一些自定义项的 ListView ,我需要更新它,我会这样做

public void updateList(List<item> newItems)
{
if (adapter == null)
{
itemList.addAll(newItems);
adapter = new SomeAdapter(layoutInflator, itemList);
listView.setAdapter(adapter);
} else
{
// lets find all the duplicates and do all the updating
List<item> nonDuplicateItems = new ArrayList<item>();
for (Item newItem : newItems)
{
boolean isDuplicate = false;
for (Item oldItem : itemList)
{
// are these the same item?
if (newItem.id == oldItem.id)
{
isDuplicate = true;
// update the item
olditem.text1 = newItem.text1;
oldItem.text2 = newItem.text2;
}
}

if (isDuplicate == false)
{
// add the new item
nonDuplicateItems.add(newItem);
}
}

// I have tried just adding these new ones to itemList,
// but that doesnt seem to make the listview update the
// views for the old ones, so I thought thuis might help
// by clearing, merging, and then adding back
nonDuplicateItems.addAll(itemList);
itemList.clear();
itemList.addAll(nonDuplicateItems);

// finally notify the adapter/listview
adapter.notifyDataSetChanged();
}
}

现在 ListView 将始终更新以显示新项目,但不会更新现有项目的 View 。

这是真正的关键,告诉我这是 View 的问题:如果我调用 adapter.getItem(position); 一个更新的预先存在的项目,返回的项目将显示更新的更改(意味着 text1 和 text2 将保留它们的新值)即使它没有反射(reflect)在 ListView 中!

如果我调用 listView.invalidateViews(); 那么 ListView 将显示更新,但是我有两个问题,有时它会闪烁,有时,只是有时如果我调用它并且它在 notifyDataSetChanged 完成到达 ListView 之前运行,我收到“ ListView 未通知数据更改”错误!

有人知道吗?

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder viewHolder;
if (convertView == null)
{
convertView = layoutInflator.inflate(R.layout.item_comment, null);
// when the holder is created it will find the child views
// it will then call refreshHolder() on itself
viewHolder = new ViewHolder(convertView, position);
convertView.setTag(viewHolder);
} else
{
viewHolder = ((ViewHolder) convertView.getTag());
viewHolder.refreshHolder(position);
}
return convertView;
}

public void refreshHolder(int position)
{
this.position = position;
tvText1.setText(getItem(position).text1);
tvText2.setText(getItem(position).text2);
}

我想知道我是否应该做的是在添加到列表之前使用复制构造函数重新实例化我的所有项目。也许在通知适配器时,如果 item 仍然是相同的引用,适配器会假定没有变化,因此不会重绘该 View ?或者适配器可能只在收到通知时才为新项目绘制新 View ?

要添加另一个细节,如果我向下滚动使更新的 View 离开屏幕,然后返回它,它会在 ListView 刷新/重新制作该 View 时显示正确的信息。

我想我需要 ListView 来刷新其所有当前 View ,所以 invalidateViews(); 可能是我必须做的。

有人知道吗?

编辑:根据此处的要求,适配器会出现此问题。

public class ItemAdapter extends BaseAdapter
{

private final static int VIEWTYPE_PIC = 1;
private final static int VIEWTYPE_NOPIC = 0;

public List<Item> items;
LayoutInflater layoutInflator;
ActivityMain activity;

public ItemAdapter(List<Item> items, LayoutInflater layoutInflator, ActivityMain activity)
{
super();
this.items = new ArrayList<Item>();
updateItemList(items);
this.layoutInflator = layoutInflator;
this.activity = activity;
}

public void updateItemList(List<Item> updatedItems)
{
if (updatedItems != null && updatedItems.size() > 0)
{
// FIND ALL THE DUPLICATES AND UPDATE IF NESSICARY
List<Item> nonDuplicateItems = new ArrayList<Item>();
for (Item newItem : updatedItems)
{
boolean isDuplicate = false;
for (Item oldItem : items)
{
if (oldItem.getId().equals(newItem.getId()))
{
// IF IT IS A DUPLICATE, UPDATE THE EXISTING ONE
oldItem.update(newItem);
isDuplicate = true;
break;
}
}
// IF IT IS NOT A DUPLICATE, ADD IT TO THE NON-DUPLICATE LIST
if (isDuplicate == false)
{
nonDuplicateItems.add(newItem);
}
}

// MERGE
nonDuplicateItems.addAll(items);
// SORT
Collections.sort(nonDuplicateItems, new Item.ItemOrderComparator());
// CLEAR
this.items.clear();
// ADD BACK IN
this.items.addAll(nonDuplicateItems);
// REFRESH
notifyDataSetChanged();
}
}

public void removeItem(Item item)
{
items.remove(item);
notifyDataSetChanged();
}

@Override
public int getCount()
{
if (items == null)
return 0;
else
return items.size();
}

@Override
public Item getItem(int position)
{
if (items == null || position > getCount())
return null;
else
return items.get(position);
}

@Override
public long getItemId(int position)
{
return getItem(position).hashCode();
}

@Override
public int getItemViewType(int position)
{
Item item = getItem(position);
if (item.getPhotoURL() != null && URLUtil.isValidUrl(item.getPhotoURL()) == true)
{
return VIEWTYPE_PIC;
}
return VIEWTYPE_NOPIC;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ItemHolder itemHolder;
if (convertView == null)
{
if (getItemViewType(position) == VIEWTYPE_PIC)
{
convertView = layoutInflator.inflate(R.layout.item_pic, null);
} else
{
convertView = layoutInflator.inflate(R.layout.item, null);
}
// THIS CONSTRUCTOR ALSO CALLS REFRESH ON THE HOLDER FOR US
itemHolder = new ItemHolder(convertView, position);
convertView.setTag(itemHolder);
} else
{
itemHolder = ((ItemHolder) convertView.getTag());
itemHolder.refreshHolder(position);
}
return convertView;
}

@Override
public int getViewTypeCount()
{
return 2;
}

@Override
public boolean hasStableIds()
{
return false;
}

@Override
public boolean isEmpty()
{
return (getCount() < 1);
}

@Override
public boolean areAllItemsEnabled()
{
return true;
}

@Override
public boolean isEnabled(int position)
{
return true;
}
}

好的,我已经试过了

    @Override
public boolean hasStableIds()
{
return true;
}

@Override
public long getItemId(int position)
{
return getItem(position).hashCode();
}

还有这个

    @Override
public boolean hasStableIds()
{
return false;
}

@Override
public long getItemId(int position)
{
return getItem(position).hashCode();
}

我的哈希码是像这样使用的来自 apache 的反射生成器(应该会导致哈希根据值发生变化)

    @Override
public int hashCode()
{
return HashCodeBuilder.reflectionHashCode(this);
}

但它没有用。据我所知,stableIds 什么也没做。

编辑:

在稳定 ID 的任意组合中,这些都不起作用。再一次,与往常一样,您必须将 View 滚动到屏幕外,然后再打开才能更新。

listview.refreshDrawableState();
listview.requestLayout();
listview.invalidateViews();

最佳答案

这里有一个类似的问题,有一个可能有效的解决方案:

ListView not refreshing already-visible items

关于java - 适配器上的 notifydataSetChanged 将更新新项目,但不会更新现有项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23666101/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com