繁体   English   中英

Recyclerview + Listadapter中的项目不会在更新时重绘

[英]Items in Recyclerview + Listadapter won't redraw on update

我正在设置一个使用ListAdapter来计算更改动画的RecyclerView。 RecyclerView通过ViewModel接收数据,ViewModel通过Firebase获取列表。 显示的项目属于Mensa类。 Mensa项目可以更改其可见性,占用率或显示的距离。

我想实现两个喜欢/隐藏项目的按钮,从而改变它们在列表中的位置。 每个项目中的两个按钮允许用户喜欢或隐藏项目。 这将根据排序策略将项目移动到列表的顶部/底部,排序策略将收藏夹放在第一位,默认为第二位,最后是hiddens。

但是,当我单击按钮时,列表将重新排列,但单击的项目将不会重新绑定。 按钮保留其旧状态(和OnClickListeners),只滚动列表将调用onBind方法。 我的问题是DiffUtil.Callback吗? 我真的不知道我的代码有什么问题。

我已经在适配器的submitList方法中提供了一个新列表(这个建议来自我的案例中另一个启用了stackoverflow问题的动画),但点击的项目仍然不会重绘。

在MensaListActivity.java中

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mensa_list);

        viewModel = ViewModelProviders.of(this).get(MensaListModel.class);

        final RecyclerView recyclerView =findViewById(R.id.mensa_list_recyclerview);
        final MensaListAdapter adapter = new MensaListAdapter(this, new MensaListAdapter.ItemButtonsListener() {
            @Override
            public void visibilityButtonClicked(Mensa mensa, VisibilityPreference newVisibility) {
                viewModel.visibilityChanged(mensa, newVisibility);
            }
        });
        recyclerView.setAdapter(adapter);
        recyclerView.setHasFixedSize(false);
        recyclerView.setLayoutManager(new GridLayoutManager(this, 1, RecyclerView.VERTICAL, false));

        viewModel.getMensaData().observe(this, new Observer<LinkedList<Mensa>>() {
            @Override
            public void onChanged(LinkedList<Mensa> mensas) {
                adapter.submitList(new LinkedList<>(mensas));
            }
        });

在MensaListModel.java中

    public LiveData<LinkedList<Mensa>> getMensaData() {
        return mensaData;
    }

    // ...

    public void visibilityChanged(Mensa changedItem, VisibilityPreference newVisibility) {
        LinkedList<Mensa> newData = getMensaData().getValue();
        int index = newData.indexOf(changedItem);

        newData.remove(index);
        newData.add(changedItem);
        sortMensaData(newData);
        // sortMensaData calls postValue method

MensaListAdapter.java

public class MensaListAdapter extends ListAdapter<Mensa, MensaListAdapter.MensaViewHolder> {

    private final ItemButtonsListener listener;
    private final Context context;

    class MensaViewHolder extends RecyclerView.ViewHolder {

        TextView nameLabel;
        TextView addressLabel;
        TextView restaurantTypeLabel;
        TextView occupancyLabel;
        TextView distanceLabel;
        ImageButton favoriteButton;
        ImageButton hideButton;

        public MensaViewHolder(@NonNull View itemView) {
            super(itemView);

            // a bunch of assignments
        }

        public void bindData(final Mensa newMensa) {

            nameLabel.setText(newMensa.getName());
            addressLabel.setText(newMensa.getAddress());
            restaurantTypeLabel.setText(newMensa.getType().toString());
            String occText = "Occupancy: " + newMensa.getOccupancy().toInt();
            occupancyLabel.setText(occText);
            if (newMensa.getDistance() != -1) {
                distanceLabel.setVisibility(View.VISIBLE);
                distanceLabel.setText(Double.toString(newMensa.getDistance()));
            } else {
                distanceLabel.setVisibility(View.INVISIBLE);
            }

            switch(newMensa.getVisibility()){
                case FAVORITE:
                    favoriteButton.setImageDrawable(ResourcesCompat.getDrawable(context.getResources(), R.drawable.favorite_active, null));
                    favoriteButton.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            listener.visibilityButtonClicked(newMensa, VisibilityPreference.DEFAULT);
                        }
                    }); break;
                case DEFAULT:
                    favoriteButton.setImageDrawable(ResourcesCompat.getDrawable(context.getResources(), R.drawable.favorite_inactive, null));
                    favoriteButton.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            listener.visibilityButtonClicked(newMensa, VisibilityPreference.FAVORITE);
                        }
                    }); break;
                case HIDDEN:
                    favoriteButton.setImageDrawable(ResourcesCompat.getDrawable(context.getResources(), R.drawable.favorite_inactive, null));
                    favoriteButton.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            listener.visibilityButtonClicked(newMensa, VisibilityPreference.FAVORITE);
                        }
                    }); break;

// removed hidebutton assignments, as they're identical to the favoritebutton assignment
            }

        }
    }

    public MensaListAdapter(Context context, ItemButtonsListener listener) {
        super(DIFF_CALLBACK);
        this.context = context;
        this.listener = listener;
    }

    private static final DiffUtil.ItemCallback<Mensa> DIFF_CALLBACK =
            new DiffUtil.ItemCallback<Mensa>() {
                @Override
                public boolean areItemsTheSame(@NonNull Mensa oldItem, @NonNull Mensa newItem) {
                    return oldItem.equals(newItem);
                }

                @Override
                public boolean areContentsTheSame(@NonNull Mensa oldItem, @NonNull Mensa newItem) {
                    return oldItem.getDistance() == newItem.getDistance()
                            && oldItem.getOccupancy().equals(newItem.getOccupancy())
                            && oldItem.getVisibility().equals(newItem.getVisibility());
                }
            };

    @Override
    public int getItemViewType(int position) {
        return R.layout.mensa_list_item;
    }

    @NonNull
    @Override
    public MensaViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        final View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
        return new MensaViewHolder(view);
    }

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

    public interface ItemButtonsListener{
        void visibilityButtonClicked(Mensa mensa, VisibilityPreference newVisibility);
    }

}

Mensa.java

public class Mensa {

    private String uID;
    private String name;
    private String address;
    private Occupancy occupancy;
    private RestaurantType type;
    private VisibilityPreference visibility;
    private double latitude;
    private double longitude;
    // distance is calculated lazily as soon as location coordinates are available, -1 means not calculated.
    private double distance = -1;

    public Mensa() {

    }

    // generated by android studio
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Mensa mensa = (Mensa) o;
        return uID.equals(mensa.uID);
    }

    @Override
    public int hashCode() {
        return Objects.hash(uID);
    }

    // a bunch of getters and setters

}

1

单击收藏夹按钮(心脏)之前的列表。 相关的是心脏和眼睛按钮。

2

收藏“Akademiestraße”项目后的清单。 它改变了位置,但心脏图标没有改变,OnClickListeners仍然是相同的。

3

滚动后返回列表顶部的列表。 心脏现在已填充,OnClickListeners已更改。

在我看来,您的数据正在更新,但RecyclerView只更新订单而不是项目的视图。 在更新视图中的项目后,尝试调用适配器的notifyDataSetChanged()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM