英文:
RecyclerView updates view upon object deletion except for last object
问题
在我的应用中,我有一个显示学生ArrayList的活动,在RecyclerView中显示。学生存储在Firebase实时数据库中。用户可以添加或删除学生。当用户删除学生时,RecyclerView会更新并显示剩余的学生。
但我有一个问题。例如,假设我有5名学生。我想要逐一删除所有5名学生。其中4名学生能够正确删除,并且RecyclerView会更新并反映出这一点。只有当我删除最后一名学生时,RecyclerView不会更新,学生的CardView仍然存在。我会收到一个确认学生已删除的吐司消息,并且我可以在数据库中看到他们已被删除。如果我返回仪表盘,然后再次进入学生列表,CardView就会消失。很奇怪。
我尝试在每次删除后再次调用onStart,但没有帮助。有任何想法吗?
public class StudentListActivity extends AppCompatActivity {
// ... (其余部分未翻译)
@Override
protected void onStart() {
super.onStart();
if(ref != null){
ref.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
// 添加从Firebase获取的学生到ArrayList
if(dataSnapshot.exists()){
list = new ArrayList<>();
for(DataSnapshot ds : dataSnapshot.getChildren()){
list.add(ds.getValue(Student.class));
}
Collections.sort(list, Student.myName);
// 创建RecyclerView
recyclerView.setLayoutManager(new LinearLayoutManager(StudentListActivity.this));
StudentAdapterClass studentAdapterClass = new StudentAdapterClass(list);
recyclerView.setAdapter(studentAdapterClass);
studentAdapterClass.setOnItemClickListener(new StudentAdapterClass.OnItemClickListener() {
@Override
public void onUpdateClick(int position) {
Student student = list.get(position);
showUpdateDialog(student.getStudentId(), student.getStudentName(), student.getStudentEmail());
}
@Override
public void onDeleteClick(int position){
Student student = list.get(position);
showDeleteDialog(student.getStudentId());
}
});
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Toast.makeText(StudentListActivity.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
private void deleteStudent(String id){
// ... (删除学生的代码部分)
onStart();
}
// ...
}
public class StudentAdapterClass extends RecyclerView.Adapter<StudentAdapterClass.MyViewHolder> {
// ... (其余部分未翻译)
static class MyViewHolder extends RecyclerView.ViewHolder {
// ... (其余部分未翻译)
}
}
英文:
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);
}
}
}
});
}
}
答案1
得分: 1
每当RecyclerView的数据发生变化时,您都需要调用适配器的notifyDataSetChanged()
方法,否则RecyclerView无法正确刷新。
您可以在deleteStudent()
方法内部像这样调用它。
recyclerView.getAdapter().notifyDataSetChanged()
英文:
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()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论