RecyclerView doesn't update UI on Android 5.1.

2019-08-18 04:32发布

问题:

I have a issue that reprodusing only on Android 5.1.1 and few devices on 5.1. On the rest of versions works fine.

Recycler view have onClick listener whereI try to update View Visibility from GONE to VISIBLE or conversely. After clicking on item nothing changes on UI. Note: If I close (BackButton) Fragment and open once again - UI will be updated. Even after pressing back button I see that UI updating for few milliseconds before destroing.

I tryed to notify all adapter, current item, invalidate itemView, swap() and set adapter again without success. All methods setVisibility(), onClick, Callbacks, BindView are successfully called (debugger).

public class PhotoGalleryAdapter extends RecyclerView.Adapter<PhotoGalleryAdapter.PhotoHolder> {

    private Context context;
    private List<String> photos;
    private View.OnClickListener listener;

    public PhotoGalleryAdapter(Context context, List<String> photos, View.OnClickListener listener) {
        this.context = context;
        this.photos = photos;
        this.listener = listener;
    }

    @Override
    public PhotoGalleryAdapter.PhotoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_photo, parent, false);
        return new PhotoHolder(v, listener);
    }

    @Override
    public void onBindViewHolder(final PhotoGalleryAdapter.PhotoHolder holder, int position) {
        String photoPath = photos.get(position);
        Glide.with(context)
                .load(photoPath)
                .thumbnail(0.1f)
                .into(holder.image);

        if (Utils.getSelectedPhotos().contains(photoPath)) {
            DrawableCompat.setTint(holder.selection.getDrawable(), ContextCompat.getColor(context, R.color.white));
            holder.selection.setVisibility(View.VISIBLE);
        } else {
            holder.selection.setVisibility(View.GONE);
        }
    }

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

    public void updateDataSet(List<String> photos) {
        if (!photos.equals(this.photos)) {
            this.photos.clear();
            this.photos.addAll(photos);
            notifyDataSetChanged();
        }
    }

    class PhotoHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        @BindView(R.id.imageView) AppCompatImageView image;
        @BindView(R.id.selectionState) AppCompatImageView selection;

        private View.OnClickListener listener;

        PhotoHolder(View view, View.OnClickListener listener) {
            super(view);
            ButterKnife.bind(this, view);
            view.setOnClickListener(this);
            this.listener = listener;
        }

        @Override
        public void onClick(View view) {
           if (Utils.getSelectedPhotos().contains(photos.get(getAdapterPosition()))) {
                selection.setVisibility(View.GONE);
                Utils.getSelectedPhotos().remove(photos.get(getAdapterPosition()));
            } else {
                Utils.getSelectedPhotos().add(photos.get(getAdapterPosition()));
                DrawableCompat.setTint(selection.getDrawable(), ContextCompat.getColor(context, R.color.white));
                selection.setVisibility(View.VISIBLE);
            }
            listener.onClick(view);
        }
    }
}

And on callback:

 @Override public void onClick(View view) {
     callbacks.onPhotoSelected(Utils.getSelectedPhotos().size());
     adapter.notifyDataSetChanged(); }

回答1:

According to your PhotoGalleryAdapter .

public void updateDataSet(List<String> photos) {
    if (!photos.equals(this.photos)) {
        this.photos.clear();
        this.photos.addAll(photos);
        notifyDataSetChanged();
    }
}

And you use

if (Utils.getSelectedPhotos().contains(photoPath)) {
        DrawableCompat.setTint(holder.selection.getDrawable(), ContextCompat.getColor(context, R.color.white));
        holder.selection.setVisibility(View.VISIBLE);
} else {
        holder.selection.setVisibility(View.GONE);
}

This line Utils.getSelectedPhotos() is not update .

And your problem is callbacks.onPhotoSelected(Utils.getSelectedPhotos().size()); .

You can use updateDataSet to update UI .

When you click .And you can use like this .

Utils.setSelectedPhotos(yourList);
adapter.updateDataSet(yourList);

Edit

You should update your list first ,then use notifyDataSetChanged .

So you list did not update , you should check for it .



回答2:

Update Solution: after changing onClick to:

     @Override
            public void onClick(View view) {
               if (Utils.getSelectedPhotos().contains(photos.get(getAdapterPosition()))) {
                    Utils.getSelectedPhotos().remove(photos.get(getAdapterPosition()));
                } else {
                    Utils.getSelectedPhotos().add(photos.get(getAdapterPosition()));
                }
                notifyDataSetChanged();
                listener.onClick(view);
            }

Works good, BUT only with LinearLayoutManager. Still doesn't works with GridLayoutManager. So after calling setVisibility() twice Android works unpredictably.