Java – RecyclerView displays deleted data on the List

RecyclerView displays deleted data on the List… here is a solution to the problem.

RecyclerView displays deleted data on the List

I’ve implemented a RecyclerView with an Inbox-style sliding View. When swiping, I deleted the list item using the following method:

public void removeItem(int position) {
    countries.remove(position);
    notifyItemRemoved(position);
}

Similarly, when FAB is pressed, I use the method to add data

public void addItem(String country) {
    countries.add(country);
    notifyItemInserted(countries.size());
}

However, when I

delete a data item by swiping, it is removed from the ArrayList and RecyclerView lists, but when I add data via FAB, the deleted data still appears in the list. I checked the ArrayList dataset. This is to be expected.

enter image description here

In the screenshot above, you can see that String Test is the newly added data. I have deleted the data for the last two lines. It is displayed randomly.

Complete code for my Adapter and Activity.

public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
    private ArrayList<String> countries;
    private TextView tv_country;

public DataAdapter(ArrayList<String> countries) {
        this.countries = countries;
    }

@Override
    public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_layout, viewGroup, false);
        return new ViewHolder(view);
    }

@Override
    public void onBindViewHolder(DataAdapter.ViewHolder viewHolder, int i) {

tv_country.setText(countries.get(i));
    }

@Override
    public int getItemCount() {
        return countries.size();
    }

public void addItem(String country) {
        countries.add(country);
        notifyItemInserted(countries.size());
    }

public void removeItem(int position) {
        countries.remove(position);
        notifyItemRemoved(position);
    }
    public class ViewHolder extends RecyclerView.ViewHolder{
        public ViewHolder(View view) {
            super(view);

tv_country = (TextView)view.findViewById(R.id.tv_country);
        }
    }
}

The main activity .java

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

private ArrayList<String> countries =  new ArrayList<>();
    private DataAdapter adapter;
    private RecyclerView recyclerView;
    private  RecyclerView.LayoutManager layoutManager;

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

initViews();
    }

private void initViews(){
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(this);
        recyclerView = (RecyclerView)findViewById(R.id.card_recycler_view);
        recyclerView.setHasFixedSize(true);
        layoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(layoutManager);
        adapter = new DataAdapter(countries);
        recyclerView.setAdapter(adapter);
        countries.add("Australia");
        countries.add("India");
        countries.add("United States of America");
        countries.add("Germany");
        countries.add("Russia");
        adapter.notifyDataSetChanged();

ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
            @Override
            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                return false;
            }

@Override
            public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
                int position = viewHolder.getAdapterPosition();

if (direction == ItemTouchHelper.LEFT){

adapter.removeItem(position);

}
            }

@Override
            public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
                Paint p = new Paint();
                Bitmap icon;
                if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE){

View itemView = viewHolder.itemView;

if(dX > 0){
                        p.setColor(Color.parseColor("#388E3C"));
                        c.drawRect((float) itemView.getLeft(), (float) itemView.getTop(), dX,(float) itemView.getBottom(), p);
                        icon = BitmapFactory.decodeResource(
                                getResources(), R.drawable.ic_edit_white);
                        float height = (float) itemView.getBottom() - (float) itemView.getTop();
                        float width = height / 3;
                        RectF dest = new RectF((float) itemView.getLeft() + width ,(float) itemView.getTop() + width,(float) itemView.getLeft()+ width+width,(float)itemView.getBottom() - width);
                        c.drawBitmap(icon,null,dest,p);
                    } else {
                        p.setColor(Color.parseColor("#D32F2F"));
                        c.drawRect((float) itemView.getRight() + dX, (float) itemView.getTop(),(float) itemView.getRight(), (float) itemView.getBottom(), p);
                        icon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_delete_white);
                        float height = (float) itemView.getBottom() - (float) itemView.getTop();
                        float width = height / 3;
                        RectF dest = new RectF((float) itemView.getRight() - width - width ,(float) itemView.getTop() + width,(float) itemView.getRight() - width,(float)itemView.getBottom() - width);
                        c.drawBitmap(icon,null,dest,p);
                    }
                }

super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
            }
        };

ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
        itemTouchHelper.attachToRecyclerView(recyclerView);

}

@Override
    public void onClick(View v) {

switch (v.getId()){
            case R.id.fab:
                adapter.addItem("Test");
                Log.d("Raj",countries.toString());
                break;
        }
    }
}

I tried

I’ve tried using notifyItemRangeChanged():

public void removeItem(int position) {
    countries.remove(position);
    notifyItemRemoved(position);
    notifyItemRangeChanged(position, countries.size());
}

Solution

I’m not sure this will solve your problem, but one thing is incorrect, and that is the way you bind (bind) data. tv_country should not be part of the DataAdapter; It should be part of each individual ViewHolder. One of the reasons we use the ViewHolder pattern is to maintain a simple reference to the View in each row.

Your bind method should look similar to:

public void onBindViewHolder(DataAdapter.ViewHolder viewHolder, int i) {
    viewHolder.tv_country.setText(countries.get(i));
}

And make sure that tv_country is set to the public field of the internal ViewHolder class.

public class ViewHolder extends RecyclerView.ViewHolder{
    public TextView tv_country;
    public ViewHolder(View view) {
        super(view);
        tv_country = (TextView) view.findViewById(R.id.tv_country);
    }
}

Related Problems and Solutions