2016-01-20 83 views
3

設置我有一個RecyclerView與一個自定義適配器和自定義ViewHolder s。ViewHolder佈局更新不適用onBindViewHolder()

我知道onCreateViewHolder()方法在RecyclerView用完ViewHolders以回收並需要一個新方法時調用。所以,我只是一個充氣佈局在那裏,它傳遞到一個新的ViewHolder.

此外,onBindViewHolder()負責爲新ViewHolder已創建或由RecyclerView回收儘快填補ViewHolder數據。所以我在那裏做的是調用我的方法holder.setNode()將數據對象傳遞給ViewHolder

我看到的行爲活動第一次啓動時,所有條目都是正確的。但是,當我添加新條目或刪除現有條目時,情況開始變得有點滑稽。

  • titleTextView始終設置正確
  • 看似隨意的主要佈局的背景顏色,我假設,因爲RecyclerView被重複使用舊的
  • 一樣我已經實現了自定義視圖,即使我無效,並傳遞哪些改變它的外觀新的價值明顯

所以我想知道:爲什麼不盡快觀點得到重用在onBindViewHolder()改變這些值?或者如果我錯了,佈局隨機切換的真正原因是什麼?


TaskListAdapter

class TaskListAdapter extends RecyclerView.Adapter<TaskListAdapter.TaskViewHolder> { 

private ArrayList<NodeHandler.DbNode> dbNodeList = new ArrayList<>(); 
... 

@Override 
public TaskViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.small_task_view, parent, false); 
    return new TaskViewHolder(v); 
} 

@Override 
public void onBindViewHolder(TaskViewHolder holder, int position) { 
    final NodeHandler.DbNode dbNode = dbNodeList.get(position); 
    holder.setNode(dbNode); 
    holder.wrapper.findViewById(R.id.card_details).setVisibility(View.GONE); 
} 

... 

public static class TaskViewHolder extends RecyclerView.ViewHolder implements ItemTouchHelperViewHolder { 
    private FrameLayout wrapper; 
    private TextView title; 
    private NodeHandler.DbNode dbNode; 

    public TaskViewHolder(View view) { 
     ... 
    } 

    public void setTitle(String str) { 
     title.setText(str); 
    } 

    public void setMarkers(@IntRange(from = 1, to = Node.MAX_URGENCY) int urgency, @IntRange(from = 1, to = Node.MAX_IMPORTANCE) int importance) { 
     if(!dbNode.isAppointment()) { 
      wrapper.setBackgroundColor(ContextCompat.getColor(wrapper.getContext(), R.color.lightGray)); 
     } 
     ((QuadrantView) wrapper.findViewById(R.id.quadrant_view)).setDimensions(importance, urgency); 
     // setDimensions will invalidate the view 
    } 

    public void setNode(NodeHandler.DbNode dbNodeObject) { 
     this.dbNode = dbNodeObject; 
     setTitle(dbNode.toString()); 
     setMarkers(dbNode.getUrgency(), dbNode.getImportance()); 
     setTips(); 
    } 
} 
} 

讓我知道你什麼都可以在這裏無關緊要。我很樂意相應地更新問題。

回答

6

只要視圖得到重用,值就確實在onBindViewHolder中更改。

看似隨意切換佈局的真正原因是onBindViewHolder目前的實現方式是假設ViewHolder是剛創建並且第一次被綁定。首先將它們設置爲其他值或

    1. 重置ViewHolder的所有值設置爲默認值:onBindViewHolder應改爲在假定ViewHolder束縛被重用,因此要麼一的方式來實現確保所有內容都設置在onBindViewHolder之內,所以人們不能說它曾經被綁定到別的東西上。

    隨機背景顏色變化:

    你是對懷疑該隨機背景顏色問題是由RecyclerView重用ViewHolder小號引起的。

    爲什麼發生這種情況的原因是因爲下面的代碼:

    if(!dbNode.isAppointment()) { 
         wrapper.setBackgroundColor(ContextCompat.getColor(wrapper.getContext(), R.color.lightGray)); 
        } 
    

    它只設置背景,如果ViewHolder不預約。因此,如果正在重用的ViewHolder以前不是用於預約,而是目前用於預約的一個,則背景色將不合適。

    解決這個問題,執行以下任一:

    • 設置ViewHolder的背景顏色到一些默認顏色前的if語句被執行(根據上述方案1):

      wrapper.setBackgroundColor(/* default background color */); 
      if(!dbNode.isAppointment()) { 
          wrapper.setBackgroundColor(ContextCompat.getColor(wrapper.getContext(), R.color.lightGray)); 
      } 
      
    • 一個else塊添加到if語句到ViewHolder的背景顏色設置爲適當的顏色(按照上述方案2)

      if(!dbNode.isAppointment()) { 
          wrapper.setBackgroundColor(ContextCompat.getColor(wrapper.getContext(), R.color.lightGray)); 
      } 
      else 
      { 
          wrapper.setBackgroundColor(/* appointment background color */); 
      } 
      
    • 倍率的RecyclerView.AdaptergetItemViewType返回基於dbNode.isAppointment()不同視圖類型,以及用於顯示它們中的每

    P.S.創建不同的亞類ViewHolder我不知道什麼問題可能是關於自定義視圖...對不起

  • +0

    嘿,我愣住了。完全忽略了這一點。我剛剛做到這一點,以便自定義視圖被替換爲全新的自定義視圖,但它顯然是可怕的。我會問一個不同的問題。謝謝! – Yorrd

    +0

    不客氣! :) – Eric