0

在此处输入图像描述

在此处输入图像描述

我现在正在开发锻炼日志应用程序。

两个项目 ( routine and routine detail) 用 表示one recycler view and adapter

如果我单击添加例程按钮,则会添加一个例程项,并且例程基本上有一个例程详细项。

日常项目有按钮add or delete routine detail items

我曾经DiffUtil更新项目。

areItemsTheSame()中,我曾经hashCode比较oldListnewList

但是,在添加或删除项目时会出现一个原因不明的问题。(不是错误)。

如果我在添加例程项目和详细项目后单击删除按钮,它首先运行良好。

除非按下上一个例程项的删除按钮,否则下一个例程项的例程详细按钮不能添加或删除。

如果上一个例程项目的删除按钮被按下,然后下一个项目的按钮被按下,则执行添加或删除。

为什么是这样?

当您使用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;
    }
}
4

0 回答 0