【发布时间】:2021-03-16 18:50:15
【问题描述】:
我附上了一张图片来帮助你理解我的问题。
我正在制作一个锻炼应用程序。
当按钮被按下时,例程被添加 在添加的例程中,可以再次使用按钮添加详细数据(set、lbs、reps)。
所以,我使用的是two type RecyclerView(页脚除外)。
我使用DiffUtil 来更新正在添加的项目。
我在进行测试时发现了一个奇怪的现象。 (见照片)
这不是错误,所以我无法弄清楚它有什么问题。
输入数据后,当我添加了一些明细项时,首先输入的数据的值出现在后面添加的项中。
如果我在添加许多项目后滚动,数据会随机移动。
但是,当您添加大量项目或滚动时,会出现这种现象。
怎么了?
RoutineAdapter.java
public class RoutineAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
final static int TYPE_ROUTINE = 1;
final static int TYPE_ROUTINE_DETAIL = 2;
final static int TYPE_ROUTINE_FOOTER = 3;
private Context context;
private List<Object> mItems = new ArrayList<>();
OnRoutineItemClickListener routinelistener;
OnRoutineAddClickListener routineAddListener;
public void updateRoutineList(List<Object> newRoutineList) {
final RoutineDiffUtil diffCallback = new RoutineDiffUtil(this.mItems, newRoutineList);
final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
this.mItems.clear();
this.mItems.addAll(newRoutineList);
diffResult.dispatchUpdatesTo(this);
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
View itemView;
if(viewType == TYPE_ROUTINE){
itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.routine_item, parent, false);
return new RoutineViewHolder(itemView);
}
else if(viewType == TYPE_ROUTINE_DETAIL){
itemView = LayoutInflater.from(context).inflate(R.layout.routine_detail_item, parent, false);
return new RoutineDetailViewHolder(itemView);
}
else {
itemView = LayoutInflater.from(context).inflate(R.layout.add_routine_item, parent, false);
return new RoutineAddFooterViewHolder(itemView);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Object obj;
switch (getItemViewType(position)) {
case TYPE_ROUTINE:
obj = mItems.get(position);
setRoutineData((RoutineViewHolder) holder, (RoutineModel) obj);
break;
case TYPE_ROUTINE_DETAIL:
obj = mItems.get(position);
RoutineDetailModel item = (RoutineDetailModel) obj;
((RoutineDetailViewHolder) holder).setDetailItem(item);
break;
case TYPE_ROUTINE_FOOTER:
break;
}
}
@Override
public int getItemCount() {
if(mItems == null)
return -1;
return mItems.size() + 1; // for footer
}
@Override
public int getItemViewType(int position) {
if(position == mItems.size()) {
return TYPE_ROUTINE_FOOTER;
}
else {
Object obj = mItems.get(position);
if(obj instanceof RoutineModel) {
return TYPE_ROUTINE;
}
else {
// obj instanceof RoutineDetailModel
return TYPE_ROUTINE_DETAIL;
}
}
}
// add routine interface
public interface OnRoutineAddClickListener {
public void onAddRoutineClick();
}
public void setOnAddRoutineClickListener(OnRoutineAddClickListener listener) {
this.routineAddListener = listener;
}
// details add / remove interface
public interface OnRoutineItemClickListener {
public void onAddBtnClicked(int curRoutinePos);
public void onDeleteBtnClicked(int curRoutinePos);
public void onWritingCommentBtnClicked(int curRoutinePos);
}
public void setOnRoutineClickListener(OnRoutineItemClickListener listener) {
this.routinelistener = listener;
}
private class RoutineViewHolder extends RecyclerView.ViewHolder {
public TextView routine;
public Button addSet;
public Button deleteSet;
public Button comment;
public RoutineViewHolder(@NonNull View itemView) {
super(itemView);
initViews();
addSet.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(routinelistener != null && getAdapterPosition() != RecyclerView.NO_POSITION)
routinelistener.onAddBtnClicked(getAdapterPosition());
}
});
deleteSet.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(routinelistener != null && getAdapterPosition() != RecyclerView.NO_POSITION)
routinelistener.onDeleteBtnClicked(getAdapterPosition());
}
});
comment.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(routinelistener != null && getAdapterPosition() != RecyclerView.NO_POSITION)
routinelistener.onWritingCommentBtnClicked(getAdapterPosition());
}
});
}
}
private class RoutineDetailViewHolder extends RecyclerView.ViewHolder {
public TextView set;
public TextView weight;
public RoutineDetailViewHolder(@NonNull View itemView) {
super(itemView);
initViews();
}
private void initViews() {
set = itemView.findViewById(R.id.set);
weight = itemView.findViewById(R.id.weight);
}
private void setDetailItem(RoutineDetailModel item) {
set.setText(item.getSet().toString() + "set");
}
}
}
RoutineDiffUtil.java
public class RoutineDiffUtil extends DiffUtil.Callback {
private List<Object> oldRoutineList;
private List<Object> newRoutineList;
public RoutineDiffUtil(List<Object> oldRoutineList, List<Object> newRoutineList) {
this.oldRoutineList = oldRoutineList;
this.newRoutineList = newRoutineList;
}
@Override
public int getOldListSize() {
return oldRoutineList.size();
}
@Override
public int getNewListSize() {
return newRoutineList.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
Object oldObj = oldRoutineList.get(oldItemPosition);
Object newObj = newRoutineList.get(newItemPosition);
if (oldObj instanceof RoutineModel && newObj instanceof RoutineModel) {
return ((RoutineModel) oldObj).id == ((RoutineModel) newObj).id;
}
else if (oldObj instanceof RoutineDetailModel && newObj instanceof RoutineDetailModel) {
return ((RoutineDetailModel) oldObj).id == ((RoutineDetailModel) newObj).id;
}
else if(oldObj instanceof RoutineModel && newObj instanceof RoutineDetailModel) {
return false;
}
else {
return false;
}
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return (oldRoutineList.get(oldItemPosition)).equals(newRoutineList.get(newItemPosition));
}
}
RoutineDetailModel.java
public class RoutineDetailModel {
public int id;
private int set = 1;
private int weight;
public RoutineDetailModel() {
Random random = new Random();
this.id = random.nextInt();
}
public RoutineDetailModel(int set) {
Random random = new Random();
this.id = random.nextInt();
this.set = set+1;
}
public Integer getSet() {
return set;
}
public int getId() {
return id;
}
@Override
public int hashCode() {
return Objects.hash(set, weight);
}
@Override
public boolean equals(@Nullable Object obj) {
if(obj != null && obj instanceof RoutineDetailModel) {
RoutineDetailModel model = (RoutineDetailModel) obj;
if(this.id == model.getId()) {
return true;
}
}
return false;
}
}
【问题讨论】:
标签: android android-recyclerview android-diffutils