我现在正在开发锻炼日志应用程序。
两个项目 ( routine and routine detail
) 用 表示one recycler view and adapter
。
如果我单击添加例程按钮,则会添加一个例程项,并且例程基本上有一个例程详细项。
日常项目有按钮add or delete routine detail items
。
我曾经DiffUtil
更新项目。
在areItemsTheSame()
中,我曾经hashCode
比较oldList
和newList
。
但是,在添加或删除项目时会出现一个原因不明的问题。(不是错误)。
如果我在添加例程项目和详细项目后单击删除按钮,它首先运行良好。
除非按下上一个例程项的删除按钮,否则下一个例程项的例程详细按钮不能添加或删除。
如果上一个例程项目的删除按钮被按下,然后下一个项目的按钮被按下,则执行添加或删除。
为什么是这样?
当您使用hashCode comparison
.
但是,equals()
这不会发生并且工作正常。
相反,每次添加或删除项目时,整个项目都会闪烁更新。
我必须如何定义 DiffUtil 类?
代码
例程模型.java
public class RoutineModel {
private ArrayList<RoutineDetailModel> routineDetailList;
private String routine;
public RoutineModel(String routine) {
this.routine = routine;
}
public void addDetail(RoutineDetailModel item) {
if(routineDetailList == null) {
routineDetailList = new ArrayList<>();
}
this.routineDetailList.add(item);
}
public ArrayList<RoutineDetailModel> getDetailItemList() {
return routineDetailList;
}
public int getDetailItemSize() {
return routineDetailList.size();
}
public String getRoutine() {
return routine;
}
public void removeDetails(int index) throws Exception {
this.routineDetailList.remove(index);
}
@Override
public int hashCode() {
return Objects.hash(routineDetailList, routine);
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
RoutineModel that = (RoutineModel) obj;
return Objects.equals(routine, that.routine) && Objects.equals(routineDetailList, that.routineDetailList);
}
}
例程适配器.java
public class RoutineAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
final static int TYPE_ROUTINE = 1;
final static int TYPE_ROUTINE_DETAIL = 2;
private Context context;
private List<Object> mItems = new ArrayList<>();
OnRoutineItemClickListener listener;
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();
if (viewType == TYPE_ROUTINE) {
View itemView = LayoutInflater.from(context).inflate(R.layout.routine_item, parent, false);
return new RoutineViewHolder(itemView);
}
View itemView = LayoutInflater.from(context).inflate(R.layout.routine_detail_item, parent, false);
return new RoutineDetailViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Object object = mItems.get(position);
if(object instanceof RoutineModel) {
setRoutineData((RoutineViewHolder) holder, (RoutineModel) object, position);
}
else if(object instanceof RoutineDetailModel) {
}
}
private void setRoutineData(RoutineViewHolder holder, RoutineModel routineItem, int position){
holder.routine.setText(routineItem.getRoutine());
holder.addSet.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(listener != null) listener.OnAddBtnClick(position);
}
});
holder.deleteSet.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(listener != null) listener.OnDeleteBtnClick(position);
}
});
}
public Object getRoutineItem(int position) {
if(mItems == null || position < 0 || position >= mItems.size())
return null;
return mItems.get(position);
}
@Override
public int getItemCount() {
if(mItems == null)
return -1;
return mItems.size();
}
@Override
public int getItemViewType(int position) {
Object obj = mItems.get(position);
if(obj instanceof RoutineModel) {
return TYPE_ROUTINE;
}
return TYPE_ROUTINE_DETAIL;
}
// detail add,delete click interface
public interface OnRoutineItemClickListener {
public void OnAddBtnClick(int curRoutinePos);
public void OnDeleteBtnClick(int curRoutinePos);
}
public void setOnRoutineClickListener(OnRoutineItemClickListener listener) {
this.listener = listener;
}
public class RoutineViewHolder extends RecyclerView.ViewHolder {
public TextView routine;
public Button addSet;
public Button deleteSet;
public RoutineViewHolder(@NonNull View itemView) {
super(itemView);
routine = itemView.findViewById(R.id.routine);
addSet = itemView.findViewById(R.id.add_set);
deleteSet = itemView.findViewById(R.id.delete_set);
}
}
public class RoutineDetailViewHolder extends RecyclerView.ViewHolder {
public TextView set;
public TextView weight;
public RoutineDetailViewHolder(@NonNull View itemView) {
super(itemView);
set = itemView.findViewById(R.id.set);
weight = itemView.findViewById(R.id.weight);
}
}
}
RoutineDiffUtil.java
public class RoutineDiffUtil extends DiffUtil.Callback {
private List<Object> oldRoutineList;
private List<Object> newRoutineList;
public RoutineDiffUtil(List<Object> oldRoutineList) {
this.oldRoutineList = oldRoutineList;
newRoutineList = new ArrayList<>();
}
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) {
// boolean result = oldRoutineList.equals(newRoutineList); // work well
boolean result = oldRoutineList.get(oldItemPosition).hashCode() == newRoutineList.get(newItemPosition).hashCode();
return result;
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldRoutineList.get(oldItemPosition).equals(newRoutineList.get(newItemPosition));
}
}
MainActivity.java
public class WriteRoutineActivity extends AppCompatActivity {
Button add_routine_btn;
TextView title;
RecyclerView routine_rv;
LinearLayoutManager routineLayoutManger;
RoutineAdapter routineAdapter;
List<RoutineModel> items;
List<String> titleData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_write_routine);
initViews();
setPageTitle(getIntent());
setRoutineRecyclerview();
items = new ArrayList<>();
routineAdapter = new RoutineAdapter();
routine_rv.setAdapter(routineAdapter);
add_routine_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
WorkoutListDialogFragment routineDialog = new WorkoutListDialogFragment();
routineDialog.show(getSupportFragmentManager(), "RoutineListDialog");
}
});
routineAdapter.setOnRoutineClickListener(new RoutineAdapter.OnRoutineItemClickListener() {
@Override
public void OnAddBtnClick(int routinePos) {
Object obj = routineAdapter.getRoutineItem(routinePos);
if(obj instanceof RoutineModel) {
RoutineModel item = (RoutineModel) obj;
item.addDetail(new RoutineDetailModel());
routineAdapter.updateRoutineList(getDataToBeDisplayed());
}
}
@Override
public void OnDeleteBtnClick(int routinePos) {
Object item = routineAdapter.getRoutineItem(routinePos);
if(item instanceof RoutineModel) {
RoutineModel routineModel = (RoutineModel) item;
if(routineModel.getDetailItemSize() > 1) {
try {
routineModel.removeDetails(routineModel.getDetailItemSize() - 1);
} catch (Exception e) {
e.printStackTrace();
}
}
else { // if delete item exists only one
items.remove(routineModel);
}
routineAdapter.updateRoutineList(getDataToBeDisplayed());
}
}
});
}
public void addRoutine(String routine) {
RoutineModel routineModel = new RoutineModel(routine);
RoutineDetailModel routineDetailModel = new RoutineDetailModel();
routineModel.addDetail(routineDetailModel);
items.add(routineModel);
routineAdapter.updateRoutineList(getDataToBeDisplayed());
}
private List<Object> getDataToBeDisplayed() {
List<Object> mixedList = new ArrayList<>();
for(RoutineModel rm: items){
mixedList.add(rm);
if(rm.getDetailItemList() != null && rm.getDetailItemSize() > 0){
for(RoutineDetailModel rmdetilas: rm.getDetailItemList()){
mixedList.add(rmdetilas);
}
}
}
return mixedList;
}
}