2014-07-03 41 views
1

目前我有一个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(); 

显然,这第一行是完全没有必要的,但由于某些原因,如果我删除列表中不正确更新该适配器将更新为空列表。我updateList()在TopPostFragment方法如下:

public static void updateList() 
    { 
     if(listAdapter != null) 
     { 
      listAdapter.clear(); 
      listAdapter.addAll(postList); 
      listAdapter.notifyDataSetChanged(); 
     } 
    } 

我有一种感觉,这个问题可能以某种方式来自我如何处理它在我的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; 
    } 

我已经从这里的所有代码中删除了与该问题无关的代码行。如果我将它复制到一个全新的列表中,它只是在更新列表的位置上做错了什么?

+0

看到需求光标这两个学家一个高效:https://gist.github.com/pskink/b21c932f405740011144和测试的ContentProvider https://gist.github.com/pskink/9ab862cdd0d6b0281ab4 – pskink

回答

0

如果不能看到大部分代码,就可能很难找出确切的问题。但作为我有一个工作实现的例子,你可以看看它是如何工作的。

通常,作为一个经验法则,我从来没有初始化适配器中的列表以将其设置为任何其他列表。相反,我总是使用.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; 
    } 
} 
+0

非常有趣!我会给这个镜头,是否有任何理由,而不是使用BaseAdapter,并调用一个空的超级()?这些事情都可能是我的问题吗? – AggieDev

+0

super超出了习惯,我认为它会被插入或者被编译器假定(无论是否是错误的)。我正在使用BaseAdapter,因为在这种情况下,我有两种不同的视图类型,因为以防万一需要更改,这种方式稍后会更容易。但我的主要观点是,适配器中的项目列表在构造函数中创建一次,然后再次设置。只有修改过了,我在适配器中为它做了修改方法。至今为止,在我的所有应用程序中,这对我来说工作得非常好:) – WIllJBD

+0

也是由AggieDev我希望你的意思是德克萨斯A&M,因为这是唯一真正的阿吉;)大声笑 – WIllJBD