The problem with my app is shown in the pictures above.
After entering the data, if i scroll after adding the item as scrollable, the data disappears.
As a further explanation, sometimes the entered data appears in other items that have been added.
To explain the app, it is an exercise recording app, and it uses a multi-type recycler view.
I used ListAdapter and also DiffUtil. And the picture is related to the Detail item.
TextWatcher was used to save the entered data.
I've been searching a lot to solve this.
The two most searched solutions are here
using
getItemViewType(),getItemId()->I used this method as shown in this link, but it didn't solve the problem.Using
setIsRecyclable(false)inside the holder -> This method worked. But I heard thatsetIsRecyclable(false)is a function that does notrecycle. If i use this, isn't it a good way to do it because there is no advantage to usingRecyclerView?
RoutineAdapter.java
public class RoutineListAdapter extends ListAdapter<Object, RecyclerView.ViewHolder> {
Context context;
RoutineListAdapter.OnRoutineItemClickListener routinelistener;
RoutineListAdapter.OnRoutineAddClickListener routineAddListener;
final static int TYPE_ROUTINE = 1;
final static int TYPE_ROUTINE_DETAIL = 2;
final static int TYPE_ROUTINE_FOOTER = 3;
public RoutineListAdapter(@NonNull DiffUtil.ItemCallback<Object> diffCallback) {
super(diffCallback);
}
// add routine interface
public interface OnRoutineAddClickListener {
public void onAddRoutineClick();
}
public void setOnAddRoutineClickListener(RoutineListAdapter.OnRoutineAddClickListener listener) {
this.routineAddListener = listener;
}
// add/remove detail interface
public interface OnRoutineItemClickListener {
public void onAddBtnClicked(int curRoutinePos);
public void onDeleteBtnClicked(int curRoutinePos);
public void onWritingCommentBtnClicked(int curRoutinePos);
}
public void setOnRoutineClickListener(RoutineListAdapter.OnRoutineItemClickListener listener) {
this.routinelistener = listener;
}
@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 RoutineListAdapter.RoutineViewHolder(itemView);
}
else if(viewType == TYPE_ROUTINE_DETAIL){
itemView = LayoutInflater.from(context).inflate(R.layout.routine_detail_item, parent, false);
return new RoutineListAdapter.RoutineDetailViewHolder(itemView);
}
else {
itemView = LayoutInflater.from(context).inflate(R.layout.add_routine_item, parent, false);
return new RoutineListAdapter.RoutineAddFooterViewHolder(itemView);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Object curItem;
switch (getItemViewType(position)) {
case TYPE_ROUTINE:
curItem = getItem(position);
setRoutineData((RoutineListAdapter.RoutineViewHolder) holder, (RoutineModel) curItem);
break;
case TYPE_ROUTINE_DETAIL:
curItem = getItem(position);
RoutineDetailModel item = (RoutineDetailModel) curItem;
((RoutineListAdapter.RoutineDetailViewHolder) holder).bind(item);
((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) {
item.setWeight(((RoutineDetailViewHolder) holder).weight.getText().toString());
}
});
break;
case TYPE_ROUTINE_FOOTER:
break;
}
}
private void setRoutineData(RoutineListAdapter.RoutineViewHolder holder, RoutineModel routineItem){
holder.routine.setText(routineItem.getRoutine());
}
public Object getRoutineItem(int position) {
if(getCurrentList() == null || position < 0 || position >= getCurrentList().size())
return null;
return getItem(position);
}
@Override
public int getItemCount() {
return getCurrentList().size() + 1;
}
@Override
public int getItemViewType(int position) {
if(position == getCurrentList().size()) {
return TYPE_ROUTINE_FOOTER;
}
else {
Object obj = getItem(position);
if(obj instanceof RoutineModel) {
return TYPE_ROUTINE;
}
else {
// obj instanceof RoutineDetailModel
return TYPE_ROUTINE_DETAIL;
}
}
}
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);
routine = itemView.findViewById(R.id.routine);
addSet = itemView.findViewById(R.id.add_set);
deleteSet = itemView.findViewById(R.id.delete_set);
comment = itemView.findViewById(R.id.write_comment);
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 {
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());
}
}
private class RoutineAddFooterViewHolder extends RecyclerView.ViewHolder {
TextView textView;
public RoutineAddFooterViewHolder(@NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.add_text);
ConstraintLayout regionForClick = itemView.findViewById(R.id.clickable_layout);
regionForClick.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (routineAddListener != null) {
routineAddListener.onAddRoutineClick();
}
}
});
}
}
}
UPDATED
Adapter
public class RoutineListAdapter extends ListAdapter<Object, RecyclerView.ViewHolder> {
// detail add / remove iterface
public interface OnRoutineItemClickListener {
public void onAddBtnClicked(int curRoutinePos);
public void onDeleteBtnClicked(int curRoutinePos);
public void onWritingCommentBtnClicked(int curRoutinePos);
public void onWritingWeight(int curRoutinePos, View view); // write weight
}
public void setOnRoutineClickListener(RoutineListAdapter.OnRoutineItemClickListener listener) {
if(this.routinelistener != null)
this.routinelistener = null;
this.routinelistener = listener;
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Object curItem;
switch (getItemViewType(position)) {
case TYPE_ROUTINE:
curItem = getItem(position);
setRoutineData((RoutineListAdapter.RoutineViewHolder) holder, (RoutineModel) curItem);
break;
case TYPE_ROUTINE_DETAIL:
((RoutineListAdapter.RoutineDetailViewHolder) holder).bind();
break;
case TYPE_ROUTINE_FOOTER:
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) {
routinelistener.onWritingWeight(getAdapterPosition(), itemView);
}
});
}
private void bind() {
RoutineDetailModel item = (RoutineDetailModel) getItem(getAdapterPosition());
set.setText(item.getSet().toString() + "set");
weight.setText(item.getWeight()); // Setting the saved value
}
}
Activity
public class WriteRoutineActivity extends AppCompatActivity implements WritingCommentDialogFragment.OnDialogClosedListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_write_routine);
initViews();
setPageTitle(getIntent());
setRoutineRecyclerview();
diffUtil2 = new RoutineDiffUtil2();
listAdapter = new RoutineListAdapter(diffUtil2);
items = new ArrayList<>();
routine_rv.setAdapter(listAdapter);
listAdapter.setOnRoutineClickListener(new RoutineListAdapter.OnRoutineItemClickListener() {
@Override
public void onWritingWeight(int curRoutinePos, View v) {
RoutineDetailModel item = (RoutineDetailModel) listAdapter.getRoutineItem(curRoutinePos);
EditText weight = v.findViewById(R.id.weight);
item.setWeight(weight.getText().toString()); // This is saved to set the value again when recycled.
});
}
}
If you need any other extra code, please tell me


