Android中从CommentActivity返回后评论重复的问题解决问询
兄弟,我明白你现在的困扰——每次从CommentActivity返回后,要么看不到新评论,要么旧评论和新评论重复出现,核心原因就是你同时在onCreate()和onResume()里调用了queryFirebaseDb(),导致每次返回时都会把Firebase里的评论再一次加到已有的列表里,自然就重复了。下面给你几个靠谱的解决方案,按需选就行:
方案1:最简单直接——查询前清空旧列表
这个方案改动最小,只需要在你的queryFirebaseDb()方法里,每次加载数据前先清空commentArrayList,这样每次查询都是重新加载所有数据,不会叠加旧内容。
修改你的查询方法:
private void queryFirebaseDb() { mDatabase.child("comments").child(newsTitle).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { // 关键:先清空旧数据 commentArrayList.clear(); for (DataSnapshot snapshot : dataSnapshot.getChildren()) { Comment comment = snapshot.getValue(Comment.class); commentArrayList.add(comment); } displayCommentsAdapter.notifyDataSetChanged(); // 处理无评论的显示逻辑 if (commentArrayList.isEmpty()) { noCommentsTextView.setVisibility(View.VISIBLE); commentsTextView.setVisibility(View.GONE); } else { noCommentsTextView.setVisibility(View.GONE); commentsTextView.setVisibility(View.VISIBLE); } } @Override public void onCancelled(DatabaseError databaseError) { // 这里可以加个Toast提示加载失败 } }); }
然后你可以保留onResume()里的调用,这样返回后会重新加载最新的评论,而且不会重复。
方案2:效率更高——用startActivityForResult手动添加新评论
如果不想每次都重新拉取所有评论,你可以在提交评论成功后,把新评论对象返回给DetailActivity,直接加到列表里,不用全量查询。
步骤1:修改启动CommentActivity的代码
在DetailActivity里用startActivityForResult启动评论页面:
imageButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent commentIntent = new Intent(DetailActivity.this, CommentActivity.class); commentIntent.putExtra("newsTitle", newsTitle); startActivityForResult(commentIntent, 100); // 100是自定义的请求码,随便设一个 } });
步骤2:在CommentActivity返回新评论
当评论成功添加到Firebase后,把新创建的Comment对象回传(注意Comment类要实现Parcelable或者Serializable接口):
// 评论提交成功后 Comment newComment = new Comment(userName, commentContent, timestamp); // 你的评论对象 Intent resultIntent = new Intent(); resultIntent.putExtra("new_comment", newComment); setResult(RESULT_OK, resultIntent); finish();
步骤3:在DetailActivity接收并添加新评论
重写onActivityResult方法,拿到新评论后直接加到列表:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 100 && resultCode == RESULT_OK && data != null) { Comment newComment = data.getParcelableExtra("new_comment"); commentArrayList.add(newComment); // 通知适配器添加了新项,比notifyDataSetChanged更高效 displayCommentsAdapter.notifyItemInserted(commentArrayList.size() - 1); // 更新无评论的显示状态 noCommentsTextView.setVisibility(View.GONE); commentsTextView.setVisibility(View.VISIBLE); } }
这种方式不用重新查询整个列表,只加新评论,性能更好,也不会有重复问题。
方案3:最省心——用Firebase实时监听
Firebase自带实时数据监听功能,只要设置一次,数据变化时会自动通知你,不用手动在onResume里调用查询。
步骤1:添加实时监听
在DetailActivity的onCreate里设置ChildEventListener,监听评论节点的变化:
private ChildEventListener commentListener; @Override protected void onCreate(Bundle savedInstanceState) { // ... 其他初始化代码 commentArrayList = new ArrayList<>(); displayCommentsAdapter = new DisplayCommentsAdapter(this, commentArrayList); mRecyclerView.setAdapter(displayCommentsAdapter); // 设置实时监听 commentListener = mDatabase.child("comments").child(newsTitle).addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) { // 新增评论时触发,只会执行一次每个子节点,不会重复 Comment comment = dataSnapshot.getValue(Comment.class); commentArrayList.add(comment); displayCommentsAdapter.notifyDataSetChanged(); updateCommentsVisibility(); } @Override public void onChildRemoved(DataSnapshot dataSnapshot) { // 评论被删除时触发(如果需要支持删除的话) Comment comment = dataSnapshot.getValue(Comment.class); commentArrayList.remove(comment); displayCommentsAdapter.notifyDataSetChanged(); updateCommentsVisibility(); } // 其他方法(onChildChanged、onChildMoved、onCancelled)可以留空或者按需实现 @Override public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {} @Override public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {} @Override public void onCancelled(DatabaseError databaseError) {} }); } // 单独抽离显示状态更新的方法,复用代码 private void updateCommentsVisibility() { if (commentArrayList.isEmpty()) { noCommentsTextView.setVisibility(View.VISIBLE); commentsTextView.setVisibility(View.GONE); } else { noCommentsTextView.setVisibility(View.GONE); commentsTextView.setVisibility(View.VISIBLE); } }
步骤2:移除监听避免内存泄漏
在onDestroy里移除监听,防止内存泄漏:
@Override protected void onDestroy() { super.onDestroy(); if (commentListener != null) { mDatabase.child("comments").child(newsTitle).removeEventListener(commentListener); } }
这样设置后,不管是新增、删除评论,列表都会自动更新,完全不用手动调用queryFirebaseDb(),彻底解决重复和不更新的问题。
内容的提问来源于stack exchange,提问作者Theo

