【问题标题】:RecyclerView blinking on notifyDataSetChanged();RecyclerView 在 notifyDataSetChanged() 上闪烁;
【发布时间】:2021-10-26 15:43:37
【问题描述】:

在版主将此问题作为重复问题删除之前,请阅读以下内容

好的,我尝试了不同的答案,但没有什么对我有用,例如我禁用了不起作用的动画,我正在尝试使用 this 但我没有使用 getItemID 所以我不知道如何处理它

这是我的代码

Home_Fragment.java // 好的,我只给出了我认为需要的部分代码,但如果你想查看整个代码,请告诉我我会更新它

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_home, container, false);
postRecyclerView.setItemAnimator(null);
        getData();
  return view;
    }
 private void getData() {
        databaseReference.addValueEventListener(new ValueEventListener() {
            @SuppressLint("NotifyDataSetChanged")
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                if (snapshot.exists()) {
                    shimmerFrameLayout.stopShimmer();
                    shimmerFrameLayout.setVisibility(View.GONE);
                    postRecyclerView.setVisibility(View.VISIBLE);
                    mUploads.clear();
                    for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
                        Upload upload = dataSnapshot.getValue(Upload.class);
                        assert upload != null;
                        upload.setmKey(dataSnapshot.getKey());
                        mUploads.add(upload);


                    }

                }
                postsAdapter.setUploads(mUploads);

                //notify the adapter
                postsAdapter.notifyDataSetChanged();
                loading = true;
            }


            @Override
            public void onCancelled(@NonNull DatabaseError error) {
                loading = true;
            }
        });
    }

PostAdapter_Home.java

public class PostAdapter_Home extends RecyclerView.Adapter<PostAdapter_Home.PostViewHolder> {
    public static List<Upload> mUploads;
    public Context mcontext;

    public PostAdapter_Home(Context context, List<Upload> uploads) {
        mUploads = uploads;
        mcontext = context;
    }


    @NonNull
    @Override
    public PostViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view;
        view = LayoutInflater.from(mcontext).inflate(R.layout.ex_home, parent, false);
        return new PostViewHolder(view);

    }

    @Override
    public void onBindViewHolder(@NonNull PostViewHolder holder, int position) {
        Shimmer shimmer = new Shimmer.ColorHighlightBuilder()
                .setBaseColor(Color.parseColor("#F3F3F3"))
                .setBaseAlpha(1)
                .setHighlightColor(Color.parseColor("#E7E7E7"))
                .setHighlightAlpha(1)
                .setDropoff(50)
                .build();
        ShimmerDrawable shimmerDrawable = new ShimmerDrawable();
        shimmerDrawable.setShimmer(shimmer);
        Upload uploadCurrent = mUploads.get(position);
        Glide.with(mcontext)
                .load(uploadCurrent.getmImageUrl())
                .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
                .placeholder(shimmerDrawable)
                .centerCrop()
                .fitCenter()
                .into(holder.imageView);

//        holder.imageView.setOnClickListener(view -> changeScaleType(holder, position));

    }


    @Override
    public int getItemCount() {
        return mUploads.size();
    }

    public void setUploads(List<Upload> uploads){
        mUploads=uploads;
    }
    public static class PostViewHolder extends RecyclerView.ViewHolder {

        private final ShapeableImageView imageView;

        public PostViewHolder(@NonNull View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.imagePostHome);

        }


    }
}

上传.java

package com.example.myappnotfinal.AdaptersAndMore;

import com.google.firebase.database.Exclude;

public class Upload {
    private String mImageUrl;
    private String mKey;
    private String mUserName;
    private String mComment;

    public Upload() {

    }

    public Upload(String imageUrl) {
        mImageUrl = imageUrl;
    }

    public String getmUserName() {
        return mUserName;
    }

    public void setmUserName(String mUserName) {
        this.mUserName = mUserName;
    }

    public String getmComment() {
        return mComment;
    }

    public void setmComment(String mComment) {
        this.mComment = mComment;
    }

    public String getmImageUrl() {
        return mImageUrl;
    }

    public void setmImageUrl(String mImageUrl) {
        this.mImageUrl = mImageUrl;
    }

    @Exclude
    public String getmKey() {
        return mKey;
    }

    @Exclude
    public void setmKey(String Key) {
        this.mKey = Key;
    }
}

【问题讨论】:

  • 嗯,我主要使用getItemId。它完成了这项工作。我想用来填充 RecyclerView 的列表中主要有 id。所以每个元素通常都有一个唯一 ID 字段供我使用。
  • 我该怎么办
  • 我认为我没有在网上看到任何关于如何在不使用 getItemId 的情况下解决该问题的文章。所以我建议你想办法在你的代码中使mUploads为你添加到其中的每个项目都有一个唯一的ID。
  • 请你告诉我我该怎么做或者任何文章或资源
  • 那篇中型文章是我自己使用的,当时我想修复我的。

标签: android android-recyclerview notifydatasetchanged


【解决方案1】:

试试 ListAdapter,它会为你管理所有这些动画。为了实现这一点,我们需要编写一些样板类。

首先,让我们创建适配器。

public class YourAdapter extends ListAdapter<YourModelClass, YourAdapter.YourViewHolder> {

    public YourAdapter(@NonNull DiffUtil.ItemCallback<YourModelClass> diffCallback) {
        super(diffCallback);
    }

    public static class YourViewHolder extends RecyclerView.ViewHolder {
        
        private TextView textViewId;
        private TextView textViewName;

        private YourViewHolder(View view) {
            super(view);
            textViewId = view.findViewById(R.id.textViewId);
            textViewName = view.findViewById(R.id.textViewName);
        }

        static YourViewHolder create(ViewGroup parent) {
            return new YourViewHolder(
                    LayoutInflater.from(parent.getContext())
                            .inflate(
                                    R.layout.your_layout,
                                    parent,
                                    false
                            )
            );
        }

        void bind(YourModelClass model) {
            textViewId.setText(String.valueOf(model.getId()));
            textViewName.setText(model.getName());
        }

    }

    @NonNull
    @Override
    public YourViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return YourViewHolder.create(parent);
    }

    @Override
    public void onBindViewHolder(@NonNull YourViewHolder holder, int position) {
        holder.bind(getItem(position));
    }
}

现在,让我们创建您的类来比较列表项和 DiffUtill 算法。在 areItemsTheSame 中,您需要使用唯一键来比较项目。在 areContentsTheSame 中,我们只是比较两个实例。

public class YourItemCallback extends DiffUtil.ItemCallback<YourModelClass> {

    @Override
    public boolean areItemsTheSame(@NonNull YourModelClass oldItem, @NonNull YourModelClass newItem) {
        return oldItem.getId() == newItem.getId();
    }

    @Override
    public boolean areContentsTheSame(@NonNull YourModelClass oldItem, @NonNull YourModelClass newItem) {
        return Objects.equals(oldItem, newItem);
    }
}

最后,让我们向适配器发送数据。请注意,submitList 方法接收您在适配器中指定的类型列表

ListAdapter&lt;YourModelClass, YourAdapter.YourViewHolder&gt;

List<YourModelClass> yourList = Arrays.asList(
                new YourModelClass(1, "John"),
                new YourModelClass(1, "Mac"),
                new YourModelClass(1, "Gu"),
                new YourModelClass(1, "Gabriel")
        );

RecyclerView recyclerView = findViewById(R.id.recyclerView);
YourAdapter yourAdapter = new YourAdapter(new YourItemCallback());
recyclerView.setAdapter(yourAdapter);
yourAdapter.submitList(yourList);

【讨论】:

  • 兄弟感谢您的回复,但我没有文本视图我有图像视图
  • 我的 viewHolder 只是一个例子,你可以将你的 view holder 与 imageView 一起使用。
【解决方案2】:

解决方案 #1:尝试在 RecyclerView.Adapter 中使用稳定的 ID

setHasStableIds(true) 并覆盖 getItemId(int position)。

如果没有稳定的 ID,在 notifyDataSetChanged() 之后,ViewHolders 通常分配到不同的位置。这就是我眨眼的原因。

您可以找到good explanation here.

解决方案 #2: 我从某些 url 加载图像时遇到同样的问题,然后 imageView 会闪烁。通过使用解决

notifyItemRangeInserted()    

而不是

notifyDataSetChanged()

避免重新加载那些未更改的旧数据。

【讨论】:

猜你喜欢
  • 2017-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-18
相关资源
最近更新 更多