[英]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
}
单击收藏夹按钮(心脏)之前的列表。 相关的是心脏和眼睛按钮。
收藏“Akademiestraße”项目后的清单。 它改变了位置,但心脏图标没有改变,OnClickListeners仍然是相同的。
滚动后返回列表顶部的列表。 心脏现在已填充,OnClickListeners已更改。
在我看来,您的数据正在更新,但RecyclerView只更新订单而不是项目的视图。 在更新视图中的项目后,尝试调用适配器的notifyDataSetChanged()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.