2016-01-20 80 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