Android 列表适配器不更新新项目

Android 列表适配器不更新新项目,android,listview,listadapter,Android,Listview,Listadapter,目前,我有一个ListView,它实现了无休止的列表加载,例如,它将加载X个项目,然后当用户滚动到底部时,它会执行一个AsyncTask调用来加载更多项目,然后将它们加载到列表中并更新它。目前,这一切都在起作用,但问题是,为了让它发挥作用,它必须非常低效地完成,以至于随着列表变长,加载新项目所需的时间也会变长,因为每次都会替换整个列表,这显然是不可取的。以下是我当前如何在AsyncTask获得成功响应后从中更新列表: //this first line is what makes the loa

目前,我有一个ListView,它实现了无休止的列表加载,例如,它将加载X个项目,然后当用户滚动到底部时,它会执行一个AsyncTask调用来加载更多项目,然后将它们加载到列表中并更新它。目前,这一切都在起作用,但问题是,为了让它发挥作用,它必须非常低效地完成,以至于随着列表变长,加载新项目所需的时间也会变长,因为每次都会替换整个列表,这显然是不可取的。以下是我当前如何在AsyncTask获得成功响应后从中更新列表:

//this first line is what makes the loading so slow, but without it the list returns an empty set when calling notifyDataSetChanged() on the ListAdapter
TopPostFragment.postList = new ArrayList<Post>(TopPostFragment.postList);
TopPostFragment.postList.addAll(result); //result is the new items that were received from the AsyncTask
TopPostFragment.updateList();
我觉得这个问题可能源于我在listAdapter中如何处理它,下面是我在listAdapter中如何处理它的构造函数:

List<Post> postList = null;

public PostListAdapter(Context context, int layoutResourceId, List<Post> list, int whichList, int currentFeedID) {
        super(context, layoutResourceId, list);
        postList = list;
    }

我已经从这里的所有代码中删除了与问题无关的行。如果我将列表复制到一个全新的列表中,列表只会更新,那么我错在哪里呢?

如果看不到代码的更多部分,可能很难找出确切的问题。但作为我的一个工作实现示例,您可以查看它是如何工作的

不过,一般来说,根据经验,我从不在适配器中初始化要设置为任何其他列表的列表。相反,我总是使用.add或.addAll或.remove或.clear等来确保对原始列表的引用不会丢失,并且您始终拥有适配器和listview所具有的相同列表的句柄

因此,在代码中进行搜索,并确保适配器中的列表已初始化一次,并且仅对其进行操作,并且从不将=设置为任何其他列表

public class ItemAdapter extends BaseAdapter
{

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

    private 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;
    }
}

非常有趣!我来试一试,你有没有理由改用BaseAdapter,然后调用一个空的super?这两件事中的任何一件可能是我的问题吗?super是出于习惯,我认为它会被插入到编译器中或由编译器假定,无论它是否可能是错误的。我之所以使用BaseAdapter,是因为在本例中,我使用了两种不同的视图类型,并且是因为万一需要更改某些内容,这样以后就更容易进行更改。但我这里的要点是,适配器中的项目列表在构造函数中创建了一次,然后再也没有设置过。只有曾经修改过,我在适配器中为它创建了修改方法。到目前为止,这在我所有的应用程序中都非常有效:AggieDev我希望你指的是德克萨斯A&M,因为这是唯一真正的Aggie;Lol但是,关键是您要给ListAdapter的列表,并确保在您给了适配器列表之后,您不会在代码中设置该列表。然而,由于我总是使用BaseAdapter,所以我在ListAdapter本身方面并没有遇到太多问题:Aggie确实意味着德克萨斯a&M!我将试一试并报告这是否解决了问题。查看这两个GIST以获得高效的按需游标:和测试ContentProvider
public class ItemAdapter extends BaseAdapter
{

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

    private 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;
    }
}