notifyDatasetChanged () 후 RecyclerView 깜박임 mItems.add(item);

API에서 일부 데이터를로드하고 이미지 URL과 일부 데이터를 포함하는 RecyclerView가 있으며 networkImageView를 사용하여 이미지를 지연로드합니다.

@Override
public void onResponse(List<Item> response) {
   mItems.clear();
   for (Item item : response) {
      mItems.add(item);
   }
   mAdapter.notifyDataSetChanged();
   mSwipeRefreshLayout.setRefreshing(false);
}

다음은 Adapter 구현입니다.

public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position) {
        if (isHeader(position)) {
            return;
        }
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        MyViewHolder holder = (MyViewHolder) viewHolder;
        final Item item = mItems.get(position - 1); // Subtract 1 for header
        holder.title.setText(item.getTitle());
        holder.image.setImageUrl(item.getImg_url(), VolleyClient.getInstance(mCtx).getImageLoader());
        holder.image.setErrorImageResId(android.R.drawable.ic_dialog_alert);
        holder.origin.setText(item.getOrigin());
    }

문제는 recyclerView에서 새로 고침을 할 때 처음에는 이상하게 보이는 매우 짧은 시간 동안 깜박입니다.

대신 GridView / ListView를 사용했고 예상대로 작동했습니다. 흠집이 없었습니다.

RecycleView 구성 onViewCreated of my Fragment:

mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        mRecyclerView.setHasFixedSize(true);

        mGridLayoutManager = (GridLayoutManager) mRecyclerView.getLayoutManager();
        mGridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                return mAdapter.isHeader(position) ? mGridLayoutManager.getSpanCount() : 1;
            }
        });

        mRecyclerView.setAdapter(mAdapter);

그런 문제에 직면 한 사람이 있습니까? 이유가 무엇일까요?



답변

RecyclerView.Adapter에서 안정적인 ID를 사용해보십시오.

setHasStableIds(true) 및 재정의 getItemId(int position) .

안정적인 ID없이 notifyDataSetChanged() 일반적으로 ViewHolders가 동일한 위치에 할당되지 않습니다. 그것이 제 경우에 깜박이는 이유였습니다.

여기 에서 좋은 설명을 찾을 수 있습니다 .


답변

문제 페이지 에 따르면 …. 기본 recycleview 항목 변경 애니메이션입니다 … 해제 할 수 있습니다 .. 시도해보세요.

recyclerView.getItemAnimator().setSupportsChangeAnimations(false);

최신 버전 변경

Android 개발자 블로그 에서 인용 :

이 새로운 API는 이전 버전과 호환되지 않습니다. 이전에 ItemAnimator를 구현 한 경우 대신 새 API를 래핑하여 이전 API를 제공하는 SimpleItemAnimator를 확장 할 수 있습니다. 또한 일부 메서드가 ItemAnimator에서 완전히 제거되었음을 알 수 있습니다. 예를 들어, recyclerView.getItemAnimator (). setSupportsChangeAnimations (false)를 호출했다면이 코드는 더 이상 컴파일되지 않습니다. 다음으로 바꿀 수 있습니다.

ItemAnimator animator = recyclerView.getItemAnimator();
if (animator instanceof SimpleItemAnimator) {
  ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
}

답변

이것은 단순히 작동했습니다.

recyclerView.getItemAnimator().setChangeDuration(0);

답변

일부 URL에서 이미지를로드하는 데 동일한 문제가 발생한 다음 imageView가 깜박입니다. 사용하여 해결

notifyItemRangeInserted()    

대신에

notifyDataSetChanged()

변경되지 않은 이전 데이터를 다시로드하지 않습니다.


답변

기본 애니메이션을 비활성화하려면 이것을 시도하십시오.

ItemAnimator animator = recyclerView.getItemAnimator();

if (animator instanceof SimpleItemAnimator) {
  ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
}

이것은 안드로이드 지원 23 이후 애니메이션을 비활성화하는 새로운 방법입니다.

이 이전 방식은 이전 버전의 지원 라이브러리에서 작동합니다.

recyclerView.getItemAnimator().setSupportsChangeAnimations(false)

답변

mItems당신을 뒷받침하는 컬렉션 이라고 가정하면Adapter 모든 것을 제거하고 다시 추가하는 이유는 무엇입니까? 기본적으로 모든 것이 변경되었다고 말하고 있으므로 RecyclerView는 이미지 라이브러리가 동일한 이미지 URL이더라도 뷰를 재설정하는 곳에서 제대로 처리하지 않는다고 가정하는 것보다 모든 뷰를 리 바인드합니다. 아마도 그들은 GridView에서 잘 작동하도록 AdapterView에 대한 솔루션으로 구워진 것입니다.

notifyDataSetChanged모든 뷰를 리 바인딩 할 것을 호출 하는 대신 RecyclerView가 필요한 뷰만 리 바인딩하고 아무것도 깜박이지 않도록 세분화 된 알림 이벤트 (추가 / 제거 / 이동 / 업데이트 알림)를 호출합니다.


답변

Recyclerview는 DefaultItemAnimator를 기본 애니메이터로 사용합니다. 아래 코드에서 볼 수 있듯이 항목 변경시 뷰 홀더의 알파를 변경합니다.

@Override
public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
    ...
    final float prevAlpha = ViewCompat.getAlpha(oldHolder.itemView);
    ...
    ViewCompat.setAlpha(oldHolder.itemView, prevAlpha);
    if (newHolder != null) {
        ....
        ViewCompat.setAlpha(newHolder.itemView, 0);
    }
    ...
    return true;
}

나머지 애니메이션을 유지하고 싶었지만 “깜박임”을 제거하여 DefaultItemAnimator를 복제하고 위의 3 개의 알파 라인을 제거했습니다.

새 애니메이터를 사용하려면 RecyclerView에서 setItemAnimator ()를 호출하면됩니다.

mRecyclerView.setItemAnimator(new MyItemAnimator());