使用 DataBinding 在 RecyclerView 项目中绑定图像时闪烁图像

Flicker image when bind image in RecyclerView item using DataBinding

我在 RecyclerView 项中使用 DataBinding 绑定图像,如下面的代码,然后当我重新加载所有 RecyclerView(通过 notifyDataSetChange)时,图像会闪烁
如果我不使用 DataBinding 并且只是正常设置图像,图像不会闪烁 DataBinding 我做错了什么?任何帮助或建议将不胜感激

我的 RecyclerView 适配器代码

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {
    private Context mContext;
    private List<String> list;
    public static class MyViewHolder extends RecyclerView.ViewHolder {
        ItemBinding mBinding;
        public MyViewHolder(ItemBinding mBinding) {
            super(mBinding.getRoot());
            this.mBinding = mBinding;
            mBinding.setViewHolder(this);
        }

        public int getSrc(){
            return R.drawable.ic_launcher;
        }
    }
    public RecyclerViewAdapter(Context context, List<String> moviesList) {
        this.mContext = context;
        this.list = moviesList;
    }
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        ItemBinding binding =
                DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.item,
                        parent, false);
        return new MyViewHolder(binding);
    }
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
    }
    @Override
    public int getItemCount() {
        return list.size();
    }
    @BindingAdapter({ "src" })
    public static void setImageSrc(ImageView view, int src) {
        if (src != -1) view.setImageResource(src);
    }
}

我的项目xml

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
>
    <data>
        <variable
            name="viewHolder"
            type="example.toong.testreloadimageusingglidebynotifydatasetchangewithdatabinding.RecyclerViewAdapter.MyViewHolder"
        />
    </data>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/bg_holding_three_gradient_layer"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="100dp"
            android:layout_height="100dp"
            app:src="@{viewHolder.src}"
        />

    </LinearLayout>
</layout>

演示项目:https://drive.google.com/file/d/0B_poNaia6t8kVlBfSGJ4QU9uZHc/view

有两种方法或许可以帮到您

1.Write你自己的适配器

.notifyDataSetChange() 。无法在数据绑定中正常工作

public class BindingRecyclerView {

public static abstract class ListAdapter<T, VH extends ViewHolder> extends RecyclerView.Adapter<VH> {

    protected final LayoutInflater inflater;
    protected final ObservableList<T> data;

    private final AtomicInteger refs = new AtomicInteger();

    private final ObservableList.OnListChangedCallback<ObservableList<T>> callback =
            new ObservableList.OnListChangedCallback<ObservableList<T>>() {
                @Override
                public void onChanged(ObservableList<T> sender) {
                    notifyDataSetChanged();
                }

                @Override
                public void onItemRangeChanged(ObservableList<T> sender,
                                               int positionStart, int itemCount) {
                    notifyItemRangeChanged(positionStart, itemCount);
                }

                @Override
                public void onItemRangeInserted(ObservableList<T> sender,
                                                int positionStart, int itemCount) {
                    notifyItemRangeInserted(positionStart, itemCount);
                }

                @Override
                public void onItemRangeMoved(ObservableList<T> sender,
                                             int fromPosition, int toPosition, int itemCount) {
                    for (int i = 0; i < itemCount; i++) {
                        notifyItemMoved(fromPosition + i, toPosition + i);
                    }
                }

                @Override
                public void onItemRangeRemoved(ObservableList<T> sender,
                                               int positionStart, int itemCount) {
                    notifyItemRangeRemoved(positionStart, itemCount);
                }
            };

    public ListAdapter(Context context, ObservableList<T> data) {
        this.inflater = LayoutInflater.from(context);
        this.data = data;
    }

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

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        if (refs.getAndIncrement() == 0) {
            data.addOnListChangedCallback(callback);
        }
    }

    @Override
    public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
        if (refs.decrementAndGet() == 0) {
            data.removeOnListChangedCallback(callback);
        }
    }

}

public static class ViewHolder<V extends ViewDataBinding> extends RecyclerView.ViewHolder {

    public final V binding;

    public ViewHolder(LayoutInflater inflater, @LayoutRes int layoutId, ViewGroup parent) {
        this(DataBindingUtil.<V>inflate(inflater, layoutId, parent, false));
    }

    public ViewHolder(V binding) {
        super(binding.getRoot());
        this.binding = binding;
    }
}}

2.When 您已刷新数据,使新适配器不要使用旧适配器。 它也可能有帮助

第一个 class 不是 me.But 写的,它在我们的项目中得到了解决。 当我使用 PageAdapter 它也不会通过 .notifyDataSetChange() 刷新 但是在那个适配器中,我可以使用另一种方式强制 refresh.So 我对 this.Hope 了解一点,这会有所帮助.....

我认为你缺少的步骤是你必须使用 executePendingBindings():

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
    // Normally, you'd do the binding here, but yours is static.
    holder.mBinding.executePendingBindings();
}

有关此主题的文章: https://medium.com/google-developers/android-data-binding-recyclerview-db7c40d9f0e4#.24tuxwvsh