2014-07-03 78 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