0

애니메이션을 보존하기 위해 최근 notifyDataSetChanged에서 notifyItemInserted/Changed/Removed으로 전환되었습니다.RecyclerView notifyxxx

나는 이런 상황에 처해있다. 내 어댑터 목록이 처음이다

A 
B 
C 
D 

그때 마지막 위치에 새로운 E 항목을 삽입하는 A, B 및 C를 병합 : 제거로 나는 인덱스 1 (B)를 알릴 수 있다고 생각

A 
E 

제거 후 삽입 된 새로운 인덱스 1 (E)로,하지만 예외가 말한다 어디 모르겠어요에서 들어오는 제거, 인덱스 3 (D)로, 인덱스 2 (C) : 불일치가 감지

. 잘못된 뷰 홀더 어댑터 positionViewHolder은 ...

은 그래서 아마 문제가 인덱스 1 회 통지에 의해 제기 된 생각, 그래서 E 변경으로 나는 인덱스 1 (B)에 통지를 변경, 인덱스 2 (C)를 제거하고 인덱스 3 (D)를 제거했지만 동일한 예외가 발생하여 더 이상 옵션이 표시되지 않습니다.

그런 상황에서 올바른 접근 방법은 무엇입니까?

+0

DiffUtils를 사용해 보셨습니까? – poss

+0

솔직히, 나는 그것이 무엇인지 모르겠다. ... – Alessandro

+0

Google로 검색하기 .... – Alessandro

답변

2

다른 항목의 두 세트 사이의 차이를 계산하는 유용한 클래스로 출시 된 지원 라이브러리 24.2 Diffutils와 같은 문제

을 가지고 경우 누군가가 답변없이 질문을하지합니다.

샘플 코드는 다음과 같을 수 있습니다 (두 개의 목록을 만들고 어댑터의 항목을 교환하는 버튼을 누름). DiffUtil.DiffResult는 모든 notify 호출을 처리합니다.

final List<RecyclerObject> list = new ArrayList<>(); 
    list.add(new RecyclerObject("A")); 
    list.add(new RecyclerObject("B")); 
    list.add(new RecyclerObject("C")); 
    list.add(new RecyclerObject("D")); 

    final TestAdapter adapter = new TestAdapter(list); 
    recycler.setAdapter(adapter); 

    final List<RecyclerObject> newList = new ArrayList<>(); 
    newList.add(new RecyclerObject("A")); 
    newList.add(new RecyclerObject("E")); 

    final View button = findViewById(R.id.mainButton); 
    button.setOnClickListener(v -> { 
     adapter.setList(newList); 

     DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffCallback(list, newList)); 
     diffResult.dispatchUpdatesTo(adapter); 
    }); 

Diffcallback은 자체 생성 클래스이므로 구현이 이와 유사 할 수 있습니다.

public class DiffCallback extends DiffUtil.Callback { 

    DiffCallback(final List<RecyclerObject> list, final List<RecyclerObject> newList) { 
     this.list = list; 
     this.newList = newList; 
    } 

    @Override 
    public int getOldListSize() { 
     return list.size(); 
    } 

    @Override 
    public int getNewListSize() { 
     return newList.size(); 
    } 

    @Override 
    public boolean areContentsTheSame(final int oldItemPosition, final int newItemPosition) { 
     return list.get(oldItemPosition).title.equals(newList.get(newItemPosition).title); 
    } 

} 

이 하나 덜 공상 방법이있다 (불필요한 코드 가독성을 제거) : 우리는 어댑터를 백업 항목을 "안정적"하고 동일한 항목이 동일한 identificator이 항상 것이라는 점을 보장 할 수있는 경우, recycler.adapter 허용 setHasStableIds 옵션의 경우 이를 통해 심지어 보통 notifyDatasetChanged (애니메이션을 죽이는 것) 만 사용하여 올바르게 처리 할 수 ​​있습니다. 기능의 우선 적용이 필요합니다. getItemId()

+0

이것은 정답입니다, 고마워요! – Alessandro