GregY491
GregY491

Reputation: 59

RecyclerView updates view upon object deletion except for last object

In my app, I have an activity that displays an ArrayList of students in a RecyclerView. The students are stored in Firebase Realtime Database. The user can add or delete students. When a user deletes a student, the RecyclerView updates and shows the remaining students.

But I have a problem. For example, say I had 5 students. I want to delete all 5 so I delete them one by one. 4 of the students delete correctly and the RecyclerView updates and reflects this. It's only when I delete the last student the RecyclerView doesn't update and the student CardView stays there. I get a toast message confirming the student's deletion and I can see they have been deleted in the database. If I navigate back to the dashboard and go back into the student list, the CardView then disappears. Strange.

I've tried calling onStart again after each deletion but this hasn't helped. Any ideas?

My activity:

public class StudentListActivity extends AppCompatActivity {

//firebase auth
private FirebaseAuth mAuth;

//public variables
public String currentUserAccount;
public String teacherAccountNav = "Teacher";
public String currentUserId;

//recyclerView variables
DatabaseReference ref;
ArrayList<Student> list;
RecyclerView recyclerView;
SearchView searchView;

@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_student_list);

    //get current user
    mAuth = FirebaseAuth.getInstance();
    FirebaseUser user = mAuth.getCurrentUser();
    //assert current user is not null and get current users id
    assert user != null;
    currentUserId = user.getUid();

    //getting firebase reference of current users students
    ref = FirebaseDatabase.getInstance().getReference().child("students").child(currentUserId);

    //initialise views
    recyclerView = findViewById(R.id.rv);
    recyclerView.setHasFixedSize(true);
    searchView = findViewById(R.id.searchView);

}

@Override
protected void onStart() {
    super.onStart();
    if(ref != null){
        ref.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                //add students from firebase to an array list
                if(dataSnapshot.exists()){
                    list = new ArrayList<>();
                    for(DataSnapshot ds : dataSnapshot.getChildren()){
                        list.add(ds.getValue(Student.class));
                    }

                    //sort by name
                    Collections.sort(list, Student.myName);

                    //make recycler view
                    recyclerView.setLayoutManager(new LinearLayoutManager(StudentListActivity.this));
                    StudentAdapterClass studentAdapterClass = new StudentAdapterClass(list);
                    recyclerView.setAdapter(studentAdapterClass);

                    //click listeners for buttons
                    studentAdapterClass.setOnItemClickListener(new StudentAdapterClass.OnItemClickListener() {

                        @Override
                        public void onUpdateClick(int position) {
                            //handle update click in here
                            Student student = list.get(position);

                            //show update dialog here
                            showUpdateDialog(student.getStudentId(), student.getStudentName(), student.getStudentEmail());
                        }

                        @Override
                        public void onDeleteClick(int position){
                            //handle delete click in here
                            Student student = list.get(position);

                            //show delete dialog here
                            showDeleteDialog(student.getStudentId());
                        }

                    });

                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
                Toast.makeText(StudentListActivity.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });
    }//if

  
}


//dialog box for deleting student
private void showDeleteDialog(final String studentId){
    AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);

    LayoutInflater inflater = getLayoutInflater();

    //dialog XML
    final View dialogView = inflater.inflate(R.layout.delete_student_dialog, null);

    dialogBuilder.setView(dialogView);

    final ImageButton buttonNo = dialogView.findViewById(R.id.imageButtonNo);
    final ImageButton buttonYes = dialogView.findViewById(R.id.imageButtonYes);

    final AlertDialog alertDialog = dialogBuilder.create();
    alertDialog.show();

    buttonNo.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            alertDialog.dismiss();
        }
    });

    buttonYes.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            deleteStudent(studentId);

            alertDialog.dismiss();
        }
    });
}

//delete student method
private void deleteStudent(String id){
    //get current user
    mAuth = FirebaseAuth.getInstance();
    FirebaseUser user = mAuth.getCurrentUser();
    //assert current user is not null and get current users id
    assert user != null;
    currentUserId = user.getUid();

    DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("students").child(currentUserId).child(id);

    databaseReference.removeValue();

    Toast.makeText(this, "Student Deleted", Toast.LENGTH_LONG).show();

    //clear and get new list
    onStart();

}

My adapter:

public class StudentAdapterClass extends RecyclerView.Adapter<StudentAdapterClass.MyViewHolder> {

private ArrayList<Student> list;

private OnItemClickListener mListener;

public interface OnItemClickListener{
    //click method for update button
    void onUpdateClick(int position);
    //click method for delete button
    void onDeleteClick(int position);

}

public void setOnItemClickListener(OnItemClickListener listener){
    mListener = listener;
}

public StudentAdapterClass(ArrayList<Student> list){

    this.list = list;
}


@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
     View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_holder, viewGroup, false);
     return new MyViewHolder(view, mListener);
}

@Override
public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int i) {
    myViewHolder.name.setText(list.get(i).getStudentName());
    myViewHolder.email.setText(list.get(i).getStudentEmail());

}

@Override
public int getItemCount() {

    return list.size();
}

static class MyViewHolder extends RecyclerView.ViewHolder {
    TextView name, email;
    ImageButton update, delete;
    MyViewHolder(@NonNull View itemView, final OnItemClickListener listener) {
        super(itemView);
        name = itemView.findViewById(R.id.studentName);
        email = itemView.findViewById(R.id.studentEmail);
        update = itemView.findViewById(R.id.updateButton);
        delete = itemView.findViewById(R.id.deleteButton);

        //update click listener
        update.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (listener != null){
                    int position = getAdapterPosition();
                    if(position != RecyclerView.NO_POSITION){
                        listener.onUpdateClick(position);
                    }
                }

            }
        });

        delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (listener != null){
                    int position = getAdapterPosition();
                    if(position != RecyclerView.NO_POSITION){
                        listener.onDeleteClick(position);
                    }
                }
            }
        });
    }
}

Upvotes: 0

Views: 33

Answers (1)

Weidian Huang
Weidian Huang

Reputation: 2935

Every time RecyclerView data changed, you have to call the adapter method notifyDataSetChanged(), otherwise, RecyclerView cannot refresh correctly. You can call it inside deleteStudent() method like this.

recyclerView.getAdapter().notifyDataSetChanged()

Upvotes: 1

Related Questions