45

RecyclerView를 사용하여 표시 할 카드 목록을 생성합니다. 각 카드에는 목록에서 해당 카드를 제거하는 버튼이 있습니다.안드로이드에서 notifyItemRemoved 또는 notifyDataSetChanged를 Android에서 RecyclerView로 사용

notifyItemRemoved()을 사용하여 RecyclerView에서 카드를 제거하면 항목이 제거되고 잘 움직이지만 목록의 데이터는 올바르게 업데이트되지 않습니다.

대신, 나는 으로 변경합니다. notifyDataSetChanged() 목록의 항목은 제거되고 올바르게 업데이트되지만 카드는 움직이지 않습니다.

누군가가 notifyItemRemoved() 사용 경험이 있고 notifyDataSetChanged와 다른 동작을하는 이유를 알고 있습니까? @pskink으로

private List<DetectedIssue> issues = new ArrayList<DetectedIssue>(); 

@Override 
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 
    // - get element from your dataset at this position 
    // - replace the contents of the view with that element 
    if(position >0){ 
     RiskViewHolder riskHolder = (RiskViewHolder)holder; 
     final int index = position - 1; 
     final DetectedIssue anIssue = issues.get(index); 

     riskHolder.button.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       try { 
        int index = issues.indexOf(anIssue); 
        issues.remove(anIssue); 
        notifyItemRemoved(index); 

        //notifyDataSetChanged(); 
       } catch (SQLException e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 
} 

@Override 
public int getItemCount() { 
    return (issues.size()+1); 
} 
+2

입니다 (인덱스 + 1) – pskink

+0

다른 인덱스 제거 –

+1

인덱스가 정확합니다. 대신에 notifyDataSetChanged()를 사용하면 모든 것이 잘 작동한다고 했으므로 ..... – revolutionary

답변

1

그것이 notifyItemRemoved(index+1) 내 경우 (인덱스 + 1) 있어야했다 제안, 내가 최고 지수를 예약하고 아마 때문에 : 여기

내가 사용하고 코드의 일부 peiece입니다 즉 헤더의 경우 position=0입니다.

당신은 ViewHolder 클래스에서 제거 리스너를 추가해야
-2

button.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 

        onCancel(getAdapterPosition()); 

      } 
     }); 

    private void onCancel(int position) { 
     if (position >= issues.size()) 
      return; 
     issues.remove(position); 
     notifyItemRemoved(position); 
    } 
61

사용 notifyItemRangeChanged (위치에서 getItemCount()); 이후 notifyItemRemoved (위치);
인덱스를 사용할 필요가 없으며 위치 만 사용하십시오. 아래 코드를 참조하십시오.

private List<DetectedIssue> issues = new ArrayList<DetectedIssue>(); 

@Override 
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 
    // - get element from your dataset at this position 
    // - replace the contents of the view with that element 
    if(position >0){ 
     RiskViewHolder riskHolder = (RiskViewHolder)holder; 

     riskHolder.button.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       try { 
        issues.remove(position); 
        notifyItemRemoved(position); 
        //this line below gives you the animation and also updates the 
        //list items after the deleted item 
        notifyItemRangeChanged(position, getItemCount()); 

       } catch (SQLException e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 
} 

@Override 
public int getItemCount() { 
    return issues.size(); 
} 
+0

문서에서 : "이 메서드 내에서 관련 데이터 항목을 가져 오는 동안 position 매개 변수 만 사용해야하며이 매개 변수의 복사본을 유지하면 안됩니다. 나중에 클릭 리스너에서 항목의 위치가 필요할 경우 RecyclerView .ViewHolder.getAdapterPosition(). 업데이트 된 어댑터 위치를 갖습니다. " –

+0

@Akshay Mahajan 낡은 스레드는 미안하지만'notifyItemRemoved (position);'는 (애니메이션과 함께) 잘 동작합니다. 무슨'notifyItemRangeChanged (위치, getItemCount()); '뭐하는거야? 나는 그 차이를 볼 수 없다. 고마워요 –

+0

getItemCount()가 아니어야합니다 - 위치, itemCount는 제거 된 항목 이후의 항목 수를 의미합니까? –

5

내 실수, 는 notifyItemChanged (위치) 위치의 항목을 제거 할 수 있습니다, 무기력, 그리고 위치의 항목이 + 1은 괜찮지 만 항목이 위치 + 2에서 시작, 당신은 얻을 것이다 예외, 사용하십시오 notifyItemRangeChanged (위치, getItemCount()); 이후 이후 notifyItemRemoved (위치); 이 같은

은 :

public void removeData(int position) { 
    yourdatalist.remove(position); 
    notifyItemRemoved(position); 
    notifyItemRangeChanged(position,getItemCount()); 
} 
+1

이 작업을 통해 변경 될 내용과 문제 해결 방법에 대한 세부 정보를 제공해주십시오. – AndroidMechanic

10

public void removeItem(int position) { 
    this.taskLists.remove(position); 
    notifyItemRemoved(position); 
    notifyItemRangeChanged(position, getItemCount() - position); 
} 

을 시도하고 매력처럼 작동합니다. 당신이있어 아마 때문에 당신은 RecyclerView.ViewHolder

getLayoutPosition()에서 getLayoutPosition()을 사용할 수 있습니다

0

레이아웃에서 항목의 정확한 위치를 제공하고 코드가 notifyItemRemoved를 시도

holder.removeButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       //Position for remove 
       int modPosition= holder.getLayoutPosition(); 
       //remove item from dataset 
       numbers.remove(modPosition); 
       //remove item from recycler view 
       notifyItemRemoved(modPosition); 
      } 
     }); 
+0

getAdapterPosition은 [documentation] (https://developer.android.com/reference/android/support/v7/widget/RecyclerView.ViewHolder.html#getLayoutPosition()) 상태로 사용해야합니다. 생성하는 위험이 있습니다. 불일치. –

0
**my solution looks like this** 

this way is unnecessary to use the heavy method: 
//notifyItemRangeChanged(xx,xx) 

/** 
* 
* recyclerView的item中的某一个view,获取其最外层的viewParent,也就是item对应的layout在adapter中的position 
* 
* @param recyclerView 
* @param view:can be the deep one inside the item,or the item itself . 
* @return 
*/ 
public static int getParentAdapterPosition(RecyclerView recyclerView, View view, int parentId) { 
    if (view.getId() == parentId) 
     return recyclerView.getChildAdapterPosition(view); 
    View viewGroup = (View) view.getParent(); 
    if (viewGroup != null && viewGroup.getId() == parentId) { 
     return recyclerView.getChildAdapterPosition(viewGroup); 
    } 
    //recursion 
    return getParentAdapterPosition(recyclerView, viewGroup, parentId); 
} 




//wherever you set the clickListener . 
holder.setOnClickListener(R.id.rLayout_device_item, deviceItemClickListener); 
holder.setOnLongClickListener(R.id.rLayout_device_item, deviceItemLongClickListener); 


@Override 
public boolean onLongClick(View v) { 
    final int position = ViewUtils.getParentAdapterPosition(rVDevicesList, v, R.id.rLayout_device_item); 
    return true; 
} 
관련 문제