I have a RecyclerView and an adapter which has an ArrayList of Person model. When the app starts I type the names in the EditText and press the button:
1)
2)
3)
4)
But when I log personList data in the activity, the result is:
personList: Item 0 -----> Alireza
personList: Item 1 -----> Tohid
personList: Item 2 -----> Alireza
First item is removed and last item is repeated in the first one. (My adapter is more complex, but I have reduced the code and views to focus on the main problem)
Adapter Layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Name" />
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add" />
</LinearLayout>
Adapter Class:
public class TestAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ArrayList<Person> mList;
private View.OnClickListener listener;
public TestAdapter(ArrayList<Person> mList, View.OnClickListener listener) {
this.mList = mList;
this.listener = listener;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.test_adapter_item, parent, false);
if (viewType == Person.State.FIRST.getValue()) {
return new FirstViewHolder(itemView);
} else { // if (viewType == Person.State.SECOND.getValue())
return new SecondViewHolder(itemView);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
final int pos = holder.getAdapterPosition();
final Person person = mList.get(pos);
if (holder instanceof FirstViewHolder) {
final FirstViewHolder h = (FirstViewHolder) holder;
h.tvName.setVisibility(View.GONE);
h.etName.setVisibility(View.VISIBLE);
h.etName.setText("");
h.etName.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) {
person.setFirstName(s.toString());
}
@Override
public void afterTextChanged(Editable s) {
}
});
h.btnAccept.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
person.setState(Person.State.SECOND);
notifyItemChanged(pos);
listener.onClick(v);
}
});
} else { // if (holder instanceof SecondViewHolder)
final SecondViewHolder h = (SecondViewHolder) holder;
h.tvName.setVisibility(View.VISIBLE);
h.tvName.setText(person.getFirstName());
h.etName.setVisibility(View.GONE);
h.btnAccept.setVisibility(View.GONE);
}
}
private static class FirstViewHolder extends RecyclerView.ViewHolder {
private TextView tvName;
private EditText etName;
private Button btnAccept;
private FirstViewHolder(@NonNull View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.tv_name);
etName = itemView.findViewById(R.id.et_name);
btnAccept = itemView.findViewById(R.id.button);
}
}
private static class SecondViewHolder extends RecyclerView.ViewHolder {
private TextView tvName;
private EditText etName;
private Button btnAccept;
SecondViewHolder(@NonNull View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.tv_name);
etName = itemView.findViewById(R.id.et_name);
btnAccept = itemView.findViewById(R.id.button);
}
}
@Override
public int getItemCount() {
return mList.size();
}
@Override
public int getItemViewType(int position) {
return mList.get(position).getState().getValue();
}
}
Related Part of Activity:
ArrayList<Person> personList = new ArrayList<>();
personList.add(new Person("", Person.State.FIRST));
adapter = new TestAdapter(personList, new View.OnClickListener() {
@Override
public void onClick(View v) {
if (personList.size() < 3) {
personList.add(new Person("", Person.State.FIRST));
adapter.notifyItemInserted(personList.size());
} else {
for (int i = 0; i < personList.size(); i++) {
Log.i("personList", "Item " + i + " -----> " + personList.get(i).getName());
}
}
}
});
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
What's the problem? And how can I achieve correct and real ArrayList Data?
your problem lies with addTextChangedListener, when new items are added in recycler view old TextChangedListeners arent removed. and they keep changing your list items values. you should remove those listeners when state is changed to SECOND state(which is surprisingly tricky look at this How to remove all listeners added with addTextChangedListener). or you should add this validation when onTextChanged is triggered. if (person.getState() == Person.State.FIRST)
person.setFirstName(s.toString());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With