redface
redface

Reputation: 325

Update the Recycleview adapter when a value is deleted from firebase

I have used a Recycleview using cardivew with list of data and button to delete any value. when I click button it does delete the value from firebase database but still the text and row remains in adapter in app but only when i close activity by going back and reopen then row is empty.

How can I update the recycleview instantly when I hit delete button

Here is my code

public class SubjectBooksAdapter extends RecyclerView.Adapter<SubjectBooksAdapter.MyViewHolder> {
    ArrayList<Books> bookslist;

    FirebaseDatabase database;
    DatabaseReference dbreference;


    public SubjectBooksAdapter(ArrayList<Books> bookslist){
        this.bookslist = bookslist;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout,parent,false);
        return new MyViewHolder(v);



    }

    public class MyViewHolder extends RecyclerView.ViewHolder {

   
          Button mSolved;
 




        MyViewHolder(final View itemView) {
            super(itemView);
 
            database = FirebaseDatabase.getInstance();
            dbreference = database.getReference("roomrequest");
             dbreference.keepSynced(true);

            mSolved = (Button) itemView.findViewById(R.id.book_solved);
            mSolved.setTransformationMethod(null);


            fauth = FirebaseAuth.getInstance();



        }
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {

        database = FirebaseDatabase.getInstance();
        dbreference = database.getReference("roomrequest");
        
   
        holder.mSolved.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

               



                    DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
                    DatabaseReference classicalMechanicsRef = rootRef.child("roomrequest").child("request").child(g.getRequestid());
                    ValueEventListener valueEventListener = new ValueEventListener() {

                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {
                            dataSnapshot.getRef().removeValue();
                    
                        }

                        @Override
                        public void onCancelled(@NonNull DatabaseError databaseError) {

                        }
                    };
                    classicalMechanicsRef.addListenerForSingleValueEvent(valueEventListener);

                    
                }
            
        });



 }



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

Any help is appreciated

Upvotes: 1

Views: 2129

Answers (2)

Sam Shaba
Sam Shaba

Reputation: 379

Assuming that you have a firebase reference to the node that contains your books, say 'booksRef', and you have a model class for books, say "Book.java", and each book has a unique ID say "bookID". And inside your model class you have a book ID getter say " getBookID", now add a firebase onChildEventListener() to your booksRef like below:

    booksRef.addChildEventListener(new ChildEventListener ()  {

        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
            Book addedBook = dataSnapshot.getValue(Book.class);

            bookslist.add(addedBook);
            adapter.notifyItemInserted(bookslist.size());
        }


        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {
            Book changedBook = dataSnapshot.getValue(Book.class);

            for (int i = 0; i < bookslist.size(); i++) {
                if (bookslist.get(i).getBookID().equals(changedBook.getBookID())) {
                    bookslist.set(i, changedBook);
                    adapter.notifyItemChanged(i);
                    break;
                }
            }
        }


        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {
            Book removedBook = dataSnapshot.getValue(Book.class);

            for (int i = 0; i < bookslist.size(); i++) {
                if (bookslist.get(i).getBookID().equals(removedBook.getBookID())) {
                    bookslist.remove(i);
                    adapter.notifyItemRemoved(i);
                    break;
                }
            }

        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

This will update the recycleview instantly after successful firebase childNode added, edited and deleted.

Upvotes: 0

Abhishek Dubey
Abhishek Dubey

Reputation: 945

classicalMechanicsRef.addListenerForSingleValueEvent(valueEventListener);

Firebase provide 3 types of listeners for events.Here you have used is a listener for single value event. If you just want to read the value once, you use ref.addListenerForSingleValueEvent().

Here you want is updated list from firebase, what you have to do is fetch the list again from firebase and pass it to the adapter. But as it is firebase event it will obviously delete data from the firebase database so you can remove the element from your recyclerview.

Bad Approach

If multiple users are not updating the same list then you can use ValueEventListener

 reference.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
       // set recyclverview from data
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
       // error handling
    }
});

This approach is bad because if any other user made changes in the data then your onDataChange() will be called again and again and your list would be updated.

Good Approach

  1. Register with a addListenerForSingleValueEvent .
  2. Pass all items to recycler adapter.
  3. If item gets deleted then call removeValue(); on the ref.
  4. Again make a call on firebase to check if deleted is key is null if it is null we can now update our recyclerview.
  5. Use the below method to remove item from RecyclerView.

first of all, item should be removed from the list!

mDataSet.remove(getAdapterPosition());

then:

notifyItemRemoved(getAdapterPosition());
notifyItemRangeChanged(getAdapterPosition(),mDataSet.size());

Upvotes: 2

Related Questions