Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView set the last ArrayList item data to the first item

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) enter image description here

2) enter image description here

3) enter image description here

4) enter image description here

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?

like image 561
Alireza Noorali Avatar asked Mar 24 '20 09:03

Alireza Noorali


1 Answers

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());

like image 132
Bacho Kurtanidze Avatar answered Sep 28 '22 08:09

Bacho Kurtanidze