https://ibb.co/QYBqvfG
사진 용량이 때문에 링크로 대체합니다.
EditText란에 데이터를 입력하고 아이템을 스크롤 될정도로 추가합니다.
이후 스크롤후에 다시 돌아오면 데이터가 지워져있습니다. 사진에서는 지워지는것만 나오지만
데이터를 추가로 입력하고 계속추가하다보면 이전에 입력했던 아이템의 데이터가 이후 추가된
아이템에 셋팅된채로 추가되는 경우도 보입니다. 스크롤하면 랜덤하계 지속적으로 바뀌구요.
입력한 데이터를 실시간으로 아이템으로 저장하고 다시 아이템에서 불러와 셋팅하기위해서
TextWatcher를 사용했습니다. 문제의 원인은 대충 알것같은데 해결된 원인은 잘모르겠습니다.
onBindViewHolder에서 뷰가 재사용되니까 입력된 데이터가 아이템에 추가된채로 재사용되어 추가되고 이런식으로 일어난 문제로 추측됩니다..
onBindViewHolder에서 TextWatcher를 설정했는데, 이것때문에 위 문제가 계속 일어나다가
onCreateViewHolder..그러니니까 뷰홀더의 생성자내에서 TextWatcher를 설정하니 해결되네요..
왜 해결이 된건가요?
onBindViewHolder에서 리스너를 설정하고 이걸 재활용하면 무슨일이 일어나는건가요..
데이터를 실시간으로 입력받아서 아이템에 저장하고 그 저장된 아이템의 데이터를 셋팅하는건 똑같은거같은데..
해결책이 두가지 정도 있던데 왜 이렇게 되는지 설명좀 해주시면 감사하겠습니다..
해결되기전과 후 코드 둘다 올리겠습니다.
전
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Object curItem;
switch (getItemViewType(position)) {
case TYPE_ROUTINE_DETAIL:
curItem = getItem(position);
((RoutineDetailViewHolder) holder).weight.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
((RoutineDetailModel) curItem).setWeight(((RoutineDetailViewHolder) holder).weight.getText().toString());
}
});
((RoutineListAdapter.RoutineDetailViewHolder) holder).bind((RoutineDetailModel) curItem);
break;
}
}
private class RoutineDetailViewHolder extends RecyclerView.ViewHolder {
private TextView set;
private EditText weight;
public RoutineDetailViewHolder(@NonNull View itemView) {
super(itemView);
set = itemView.findViewById(R.id.set);
weight = itemView.findViewById(R.id.weight);
}
private void bind(RoutineDetailModel item) {
set.setText(item.getSet().toString() + "set");
weight.setText(item.getWeight()); // 스크롤 됐을때 데이터 유지하기 위함.
}
}
후 (정상 코드1)- onCreateViewHolder() (뷰홀더 생성자에 리스너 설정하기)
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Object curItem;
switch (getItemViewType(position)) {
case TYPE_ROUTINE_DETAIL:
curItem = getItem(position);
((RoutineListAdapter.RoutineDetailViewHolder) holder).bind((RoutineDetailModel) curItem);
break;
}
}
private class RoutineDetailViewHolder extends RecyclerView.ViewHolder {
private TextView set;
private EditText weight;
public RoutineDetailViewHolder(@NonNull View itemView) {
super(itemView);
set = itemView.findViewById(R.id.set);
weight = itemView.findViewById(R.id.weight);
weight.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
RoutineDetailModel item = (RoutineDetailModel) getItem(getAdapterPosition());
item.setWeight(weight.getText().toString());
}
});
}
private void bind(RoutineDetailModel item) {
set.setText(item.getSet().toString() + "set");
weight.setText(item.getWeight());
}
}
후 (정상코드2) - 리스너 삭제하고 다시 리스너 추가하기
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Object curItem;
switch (getItemViewType(position)) {
case TYPE_ROUTINE_DETAIL:
curItem = getItem(position);
((RoutineListAdapter.RoutineDetailViewHolder) holder).bind((RoutineDetailModel) curItem);
break;
}
}
private class RoutineDetailViewHolder extends RecyclerView.ViewHolder {
private TextView set;
private EditText weight;
private TextWatcher textWatcher;
public RoutineDetailViewHolder(@NonNull View itemView) {
super(itemView);
set = itemView.findViewById(R.id.set);
weight = itemView.findViewById(R.id.weight);
}
private void bind(RoutineDetailModel item) {
weight.removeTextChangedListener(textWatcher);
textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
item.setWeight(weight.getText().toString());
}
};
weight.addTextChangedListener(textWatcher);
weight.setText(item.getWeight());
set.setText(item.getSet().toString() + "set");
}
}