简体   繁体   中英

RecyclerView shows removed data on List

I have implemented a RecyclerView with inbox style swipe view. When swiped, I removed the list item using the method below:

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

Similarly when the FAB is pressed I add data using the method,

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

However, when I remove a data item by swiping, it is removed from the ArrayList and RecyclerView list, but when I add data by FAB the removed data is still displayed in the list. I checked the ArrayList data set. It is as intended.

在此输入图像描述

In the above screenshot you can see the String Test is the newly added data. The data in last two row I already deleted. It gets randomly displayed.

The complete code of 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);
        }
    }
}

MainActivity.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;
        }
    }
}

What I have tried

I have tried using notifyItemRangeChanged() like this:

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

I can't be sure that this will solve your problem, but one thing that is incorrect is how you are binding your data. tv_country should not be a part of the DataAdapter; it should be a part of each individual ViewHolder. One of the reasons we use the ViewHolder pattern is to maintain an easy reference to the views in each row.

Your bind method should end up similar to:

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

And be sure to make tv_country a public field of your inner 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);
    }
}

Not sure I understood what is happening a 100%, but why are you actually trying to animate yourself? If you implement getItemId() and hasStableIds() if I remember correctly, you just should tell the recyclerview which element was removed or added (like you actually do).

onSwiped方法中,添加viewHolder.setIsRecyclable(false);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM