Anne
Anne

Reputation: 41

Other items duplicate when I delete an item from RecyclerView

I'm using Firebase Realtime Database and a RecyclerView that displays the items of the database. I want the users to be able to delete an item from both the view and the database by long-clicking on it, and it works well for the database, but when the item is deleted in the view, it duplicates other items (only in the view, not in the database). For example, if i have 3 items a, b and c, and i delete b, i will have items a, c, a and c in my View. If after that i delete one of the c, for example the second one, i get a, c, a and a. And the item c disappears from my Database. How can I fix it ? Here is my ItemDisplayActivity:

public class ItemDisplayActivity extends AppCompatActivity {
private RecyclerView mItemRecyclerView;
private ItemAdapter mItemAdapter;
private ArrayList<Item> mItemList = new ArrayList<Item>();
FirebaseDatabase database;
DatabaseReference myRef;
private static final String TAG = NewItemActivity.class.getSimpleName();
private Context context;
private int realSize = 1;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_item_display);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    context = this;

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            startActivity(new Intent(ItemDisplayActivity.this, NewItemActivity.class));
        }
    });


    mItemRecyclerView = (RecyclerView) findViewById(R.id.activity_main_item_recycler_view);
    database = FirebaseDatabase.getInstance();
    myRef = database.getReference("items");

    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this);
    mItemRecyclerView.setLayoutManager(mLayoutManager);

    mItemRecyclerView.setItemAnimator(new DefaultItemAnimator());

    mItemAdapter = new ItemAdapter(this, mItemList);

    mItemRecyclerView.setAdapter(mItemAdapter);

    final String currentUserEmail = FirebaseAuth.getInstance().getCurrentUser().getEmail();

    String[] userList2 = getIntent().getStringArrayExtra(KEY);
    final String[] allUsers = new String[11];


    allUsers[0] = currentUserEmail;
    if (userList2 != null) {
        for (int i = 0; i < 10; i++) {
            if (userList2[i] != null) {
                allUsers[i + 1] = userList2[i];
                realSize++;
            }
        }
    }


    myRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            // This method is called once with the initial value and again
            // whenever data at this location is updated.

            for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
                Item value = dataSnapshot1.getValue(Item.class);
                String valueEmail = "";
                if (value.getUserEmail() != null) {
                    valueEmail = value.getUserEmail();
                }
                for (int i = 0; i < realSize; i++) {
                    if (allUsers[i].equals(valueEmail)) {
                        Item item = new Item();
                        String name = value.getName();
                        Integer amount = value.getAmount();
                        String container = value.getContainer();
                        String expiryDate = value.getExpiryDate();
                        String reminderDate = value.getReminderDate();
                        String owner = value.getOwner();
                        Double price = value.getPrice();
                        item.setName(name);
                        item.setAmount(amount);
                        item.setContainer(container);
                        item.setExpiryDate(expiryDate);
                        item.setReminderDate(reminderDate);
                        item.setOwner(owner);
                        item.setPrice(price);
                        mItemList.add(item);
                        mItemAdapter.notifyDataSetChanged();
                    }
                }

            }

        }

        @Override
        public void onCancelled(DatabaseError error) {
            // Failed to read value
            Log.w("Hello", "Failed to read value.", error.toException());
        }
    });

    /**
     * Creates an instance of the item touch listener
     * Implements an onClick method
     */
    mItemRecyclerView.addOnItemTouchListener(new ItemTouchListener(getApplicationContext(),
            mItemRecyclerView, new ItemTouchListener.ClickListener() {
        /**
         * When clicking on an item, creates a toast message,
         * hides the arrival time for that row only and shows the ProgressBar on that row
         * for 2 seconds using a thread
         * Updates the arrival time for that row only.
         ​*
         * @param view
         * @param position
         */
        @Override
        public void onClick(View view, int position) {
            Toast.makeText(getApplicationContext(), "Select new amount",
                    Toast.LENGTH_LONG).show();
            final Item item = mItemList.get(position);

            // Creating alert Dialog with one Button
            AlertDialog.Builder alertDialog = new AlertDialog.Builder(ItemDisplayActivity.this);

            //AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create();

            // Setting Dialog Title
            alertDialog.setTitle("New Amount");

            // Setting Dialog Message
            alertDialog.setMessage("Enter New Amount");

            final EditText input = new EditText(ItemDisplayActivity.this);
            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.MATCH_PARENT);
            input.setLayoutParams(lp);
            alertDialog.setView(input);

            // Setting Icon to Dialog
            alertDialog.setIcon(R.drawable.banana);

            // Setting Positive "Yes" Button
            alertDialog.setPositiveButton("Update",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            // Write your code here to execute after dialog
                            Toast.makeText(getApplicationContext(), "Amount Updated", Toast.LENGTH_SHORT).show();
                            Integer newAmount = Integer.parseInt(input.getText().toString());
                            item.setAmount(newAmount);
                            mItemAdapter.notifyDataSetChanged();
                        }
                    });
            // Setting Negative "NO" Button
            alertDialog.setNegativeButton("Cancel",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            // Write your code here to execute after dialog
                            dialog.cancel();
                        }
                    });

            // closed

            // Showing Alert Message
            alertDialog.show();


        }

        //Overrides the onLongClick method
        @Override
        public void onLongClick(View view,final int position) {
            Item item = mItemList.get(position);
            mItemList.remove(position);
            mItemAdapter.notifyItemRemoved(position);
            mItemAdapter.notifyItemRangeChanged(position, mItemList.size());





            DatabaseReference myRef = FirebaseDatabase.getInstance().getReference();
            Query deleteQuery = myRef.child("items").orderByChild("name").equalTo(item.getName());

            deleteQuery.addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    for (DataSnapshot deleteSnapshot : dataSnapshot.getChildren()) {
                        deleteSnapshot.getRef().removeValue();

                        Log.d(TAG, "it tried");

                    }
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {
                    Log.e(TAG, "onCancelled", databaseError.toException());
                }
            });

            mItemAdapter.notifyDataSetChanged();


        }
    }));


}

And my ItemAdapter code:

public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ViewHolder> {
private ArrayList<Item> items;
private Context context;

public class ViewHolder extends RecyclerView.ViewHolder {
    public TextView text_name, text_amount, text_container, text_date, text_reminder_date,
            text_owner, text_price;

    public ViewHolder(View itemView) {
        super(itemView);
        text_name = (TextView) itemView.findViewById(R.id.layout_middle_name);
        text_amount = (TextView) itemView.findViewById(R.id.layout_middle_amount);
        text_container = (TextView) itemView.findViewById(R.id.layout_middle_container);
        text_date = (TextView) itemView.findViewById(R.id.layout_middle_expiry_date);
        text_reminder_date = (TextView) itemView.findViewById(R.id.layout_middle_reminder_date);
        text_owner = (TextView) itemView.findViewById(R.id.layout_right_owner);
        text_price = (TextView) itemView.findViewById(R.id.layout_right_price);

    }
}

public ItemAdapter(Context context, ArrayList<Item> items) {
    this.items = items;
    this.context = context;
}


@NonNull
@Override
public ItemAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.item_view, parent, false);

    return new ItemAdapter.ViewHolder(itemView);
}

@Override
public void onBindViewHolder(@NonNull ItemAdapter.ViewHolder holder, int position) {
    Item item = items.get(position);
    holder.text_name.setText(item.getName());
    holder.text_amount.setText(item.getAmount() + "");
    holder.text_container.setText(item.getContainer());
    holder.text_date.setText(item.getExpiryDate());
    holder.text_reminder_date.setText(item.getReminderDate());
    holder.text_owner.setText(item.getOwner());
    holder.text_price.setText(item.getPrice() + "$");


}

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

}

Upvotes: 0

Views: 2294

Answers (2)

@Override
    public void onLongClick(View view,final int position)
        Item item = mItemList.get(
        mItemList.clear();
        mItemList.remove(position);
        mItemAdapter.notifyItemRemoved(position);
        mItemAdapter.notifyItemRangeChanged(position, mItemList.size());

Try doing this it really helped me.

Upvotes: 0

Anne
Anne

Reputation: 41

I solved my problem by adding mItemList.clear(); in the onDataChange method :

myRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            mItemList.clear(); //This way the item list is updated

            for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
                Item value = dataSnapshot1.getValue(Item.class);

Upvotes: 3

Related Questions