[英]Comments in ArrayList get messed up after deletion / removal of comment in list
我的應用程序中有一個評論功能,用戶可以在其中評論彼此的帖子,也可以喜歡或不喜歡彼此的評論。 此外,如果他們對他們的評論不滿意,他們可以刪除它。 一切正常,直到我刪除評論部分,因為然后我調用notifyDataSetChanged();
或notifyItemRangeChanged();
一切都變得一團糟,因為當評論列表刷新並且我嘗試喜歡列表中的某些評論時,有時會不止一個被喜歡,或者如果我單擊“不喜歡”,有時會不止一個被不喜歡,有時既喜歡又不喜歡最終被選中。
我已經嘗試了一千種方法來修復它,但沒有任何效果。 下面我將向你們展示一些我嘗試過的事情的例子......在 onChildRemoved(); 我試過這樣:
評論活動
private void readComments() {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Comments").child(mPostId);
ChildEventListener childEventListener = new ChildEventListener() {
@Override
public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
Comment comment = dataSnapshot.getValue(Comment.class);
comment.setComment(comment.getComment());
mCommentList.add(comment);
keysList.add(dataSnapshot.getKey());
mCommentAdapter.notifyItemInserted(mCommentList.size() - 1);
}
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
mCommentAdapter.removeComment(dataSnapshot.getKey());
mRecyclerView.setAdapter(mCommentAdapter);
mCommentAdapter.notifyDataSetChanged();
}
@Override
public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
};
reference.addChildEventListener(childEventListener);
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
int index = keysList.indexOf(dataSnapshot.getKey());
mCommentList.remove(index);
mCommentAdapter.notifyItemChanged(index);
keysList.remove(index);
mCommentAdapter.notifyItemRangeChanged(index, mCommentList.size());
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
index = keysList.indexOf(dataSnapshot.getKey());
keysList.remove(index);
mCommentList.remove(index);
mCommentAdapter.notifyDataSetChanged();
}
名單還在繼續。 我已經嘗試了很多這些變體,但在刪除評論后仍然如此,當我嘗試喜歡或不喜歡列表中的評論時,不止一個人喜歡或不喜歡,有時喜歡和不喜歡最終都會被選中。
關於可能導致這種情況的想法?
CommentAdapter (我喜歡和不喜歡評論的方式)
public class CommentAdapter extends RecyclerView.Adapter<CommentAdapter.ViewHolder> {
private Context mContext;
private List<Comment> mCommentList;
private String mPostId;
private String mNotificationId;
private FirebaseUser mFirebaseUser;
public CommentAdapter(Context mContext, List<Comment> mComment, String mPostId) {
this.mContext = mContext;
this.mCommentList = mComment;
this.mPostId = mPostId;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.comment_item, parent, false);
return new CommentAdapter.ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
mFirebaseUser = FirebaseAuth.getInstance().getCurrentUser();
final Comment comment = mCommentList.get(position);
holder.comment.setText(comment.getComment());
commentLike(comment.getCommentid(), holder.commentLike);
commentDislike(comment.getCommentid(), holder.commentDislike);
getUserInfo(holder.image_profile, holder.username, comment.getPublisher());
commentLikesNumber(holder.commentLikesNumber, comment.getCommentid());
commentDislikesNumber(holder.commentDislikesNumber, comment.getCommentid());
commentResponseNumber(holder.commentResponseNumber, comment.getCommentid());
holder.iconComment.setOnClickListener(v -> {
Intent intent = new Intent(mContext, ResponseActivity.class);
intent.putExtra("commentid", comment.getCommentid());
intent.putExtra("publisherid", comment.getPublisher());
intent.putExtra("postid", mPostId);
mContext.startActivity(intent);
});
holder.commentLike.setOnClickListener(v -> {
if (holder.commentLike.getTag().equals("like") && holder.commentDislike.getTag().equals("dislike")) {
likeComment(comment.getCommentid(), mPostId, comment.getPublisher());
} else if (holder.commentLike.getTag().equals("like") && holder.commentDislike.getTag().equals("disliked")) {
likeComment(comment.getCommentid(), mPostId, comment.getPublisher());
removeDislike(comment.getCommentid());
} else {
removeLike(comment.getPublisher(), comment.getCommentid());
}
});
holder.commentDislike.setOnClickListener(v -> {
if (holder.commentDislike.getTag().equals("dislike") && holder.commentLike.getTag().equals("like")) {
dislikeComment(comment.getCommentid());
Toast.makeText(mContext, "Don't be mean", Toast.LENGTH_SHORT).show();
} else if (holder.commentDislike.getTag().equals("dislike") && holder.commentLike.getTag().equals("liked")) {
dislikeComment(comment.getCommentid());
removeLike(comment.getPublisher(), comment.getCommentid());
Toast.makeText(mContext, "Don't be mean", Toast.LENGTH_SHORT).show();
} else {
removeDislike(comment.getCommentid());
}
});
holder.image_profile.setOnClickListener(v -> {
Intent intent = new Intent(mContext, MainActivity.class);
intent.putExtra("publisherid", comment.getPublisher());
mContext.startActivity(intent);
});
//Timestamp to Date
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
Date date = new Date(timestamp.getTime());
//Current timestamp
Calendar calendar = Calendar.getInstance();
long ts = calendar.getTimeInMillis();
//Getting comment timestamp from database
long timestampOfComment = comment.getTimestamp();
//SECOND WAY
long duration = ts - timestampOfComment;
long diffInSeconds = TimeUnit.MILLISECONDS.toSeconds(duration);
long diffInMinutes = TimeUnit.MILLISECONDS.toMinutes(duration);
long diffInHours = TimeUnit.MILLISECONDS.toHours(duration);
long diffInDays = TimeUnit.MILLISECONDS.toDays(duration);
if (diffInSeconds < 10) {
holder.timestamp.setText(" \u25CF " + "Just now");
} else if (diffInSeconds > 10 && diffInSeconds < 60) {
holder.timestamp.setText(" \u25CF " + diffInSeconds + " seconds ago");
} else if (diffInSeconds > 60 && diffInMinutes == 1) {
holder.timestamp.setText(" \u25CF " + diffInMinutes + " minute ago");
} else if (diffInSeconds > 60 && diffInMinutes < 60) {
holder.timestamp.setText(" \u25CF " + diffInMinutes + " minutes ago");
} else if (diffInSeconds > 60 && diffInMinutes > 60 && diffInHours == 1) {
holder.timestamp.setText(" \u25CF " + diffInHours + " hour ago");
} else if (diffInSeconds > 60 && diffInMinutes > 60 && diffInHours > 1 && diffInHours < 24) {
holder.timestamp.setText(" \u25CF " + diffInHours + " hours ago");
} else if (diffInSeconds > 60 && diffInMinutes > 60 && diffInHours > 24 && diffInDays == 1) {
holder.timestamp.setText(" \u25CF " + diffInDays + " day ago");
} else if (diffInSeconds > 60 && diffInMinutes > 60 && diffInHours > 24 && diffInDays > 1) {
holder.timestamp.setText(" \u25CF " + diffInDays + " days ago");
}
holder.itemView.setOnLongClickListener(v -> {
if (comment.getPublisher().equals(mFirebaseUser.getUid())) {
AlertDialog alertDialog = new AlertDialog.Builder(mContext).create();
alertDialog.setTitle("Would you like to delete this comment?");
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "No", (dialog, which) -> dialog.dismiss());
alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "Yes", (dialog, which) -> {
deleteCommentNotification(mPostId, comment.getCommentid());
FirebaseDatabase.getInstance().getReference("Comments Liked").child(comment.getCommentid()).setValue(null);
FirebaseDatabase.getInstance().getReference("Comments Disliked").child(comment.getCommentid()).setValue(null);
FirebaseDatabase.getInstance().getReference("Responses").child(comment.getCommentid()).setValue(null);
Toast.makeText(mContext, "Your comment has been deleted.", Toast.LENGTH_SHORT).show();
dialog.dismiss();
});
alertDialog.show();
}
return true;
});
}
@Override
public int getItemCount() {
if (mCommentList != null) {
return mCommentList.size();
} else {
return 0;
}
}
static class ViewHolder extends RecyclerView.ViewHolder {
CircleImageView image_profile;
TextView username, comment, commentLikesNumber, commentDislikesNumber, commentResponseNumber, timestamp;
ImageView commentLike, commentDislike, iconComment;
ViewHolder(@NonNull View itemView) {
super(itemView);
image_profile = itemView.findViewById(R.id.image_profile);
comment = itemView.findViewById(R.id.comment);
username = itemView.findViewById(R.id.username);
commentLike = itemView.findViewById(R.id.icon_thumb_up_grey);
commentDislike = itemView.findViewById(R.id.icon_thumb_down_grey);
commentLikesNumber = itemView.findViewById(R.id.comment_likes_number);
commentDislikesNumber = itemView.findViewById(R.id.comment_dislikes_number);
iconComment = itemView.findViewById(R.id.icon_comment_grey);
commentResponseNumber = itemView.findViewById(R.id.comment_response_number);
timestamp = itemView.findViewById(R.id.timestamp);
}
}
private void deleteCommentNotification(String postid, String commentid) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Comments").child(postid).child(commentid);
reference.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
String notificationId = dataSnapshot.child("notificationId").getValue(String.class);
String user = dataSnapshot.child("for").getValue(String.class);
if (notificationId != null && user != null) {
FirebaseDatabase.getInstance().getReference("Notifications").child(user).child(notificationId).removeValue();
reference.removeValue();
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
private void getUserInfo(final ImageView prof_image, final TextView username, String publisherid) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Users").child(publisherid);
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
if (user != null) {
Glide.with(mContext.getApplicationContext()).load(user.getImageurl()).into(prof_image);
username.setText(user.getUsername());
} else {
prof_image.setImageResource(R.drawable.profile_placeholder);
username.setVisibility(View.GONE);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
public void removeComment(final String key) {
for (int i = 0; i < mCommentList.size(); i++) {
if (mCommentList.get(i).getCommentid().equals(key)) {
mCommentList.remove(i);
break;
}
}
}
private void commentLike(final String commentid, final ImageView imageView) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Comments Liked").child(commentid);
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (mFirebaseUser != null)
if (dataSnapshot.child(mFirebaseUser.getUid()).exists()) {
imageView.setImageResource(R.drawable.ic_thumb_up_blue);
imageView.setTag("liked");
} else {
imageView.setImageResource(R.drawable.ic_thumb_up_grey);
imageView.setTag("like");
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
private void commentDislike(final String commentid, final ImageView imageView) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Comments Disliked").child(commentid);
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (mFirebaseUser != null)
if (dataSnapshot.child(mFirebaseUser.getUid()).exists()) {
imageView.setImageResource(R.drawable.ic_thumb_down_blue);
imageView.setTag("disliked");
} else {
imageView.setImageResource(R.drawable.ic_thumb_down_grey);
imageView.setTag("dislike");
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
private void commentLikesNumber(TextView commentLikesNumber, String commentid) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Comments Liked").child(commentid);
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
long commentLikes = dataSnapshot.getChildrenCount();
if (commentLikes == 0) {
commentLikesNumber.setVisibility(View.INVISIBLE);
} else {
commentLikesNumber.setVisibility(View.VISIBLE);
commentLikesNumber.setText(String.valueOf(commentLikes));
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
private void commentDislikesNumber(TextView commentDislikesNumber, String commentid) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Comments Disliked").child(commentid);
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
long commentDislikes = dataSnapshot.getChildrenCount();
if (commentDislikes == 0) {
commentDislikesNumber.setVisibility(View.INVISIBLE);
} else {
commentDislikesNumber.setVisibility(View.VISIBLE);
commentDislikesNumber.setText(String.valueOf(commentDislikes));
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
private void commentResponseNumber(TextView commentResponseNumber, String commentid) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Responses").child(commentid);
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
long commentResponses = dataSnapshot.getChildrenCount();
if (commentResponses == 0) {
commentResponseNumber.setVisibility(View.INVISIBLE);
} else {
commentResponseNumber.setVisibility(View.VISIBLE);
commentResponseNumber.setText(String.valueOf(commentResponses));
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
private void likeComment(String commentId, String postId, String userId) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Comments Liked").child(commentId).child(mFirebaseUser.getUid());
mNotificationId = reference.push().getKey();
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("notificationId", mNotificationId);
hashMap.put("commentid", commentId);
hashMap.put("userid", mFirebaseUser.getUid());
reference.setValue(hashMap);
HashMap<String, Object> hashMap1 = new HashMap<>();
hashMap1.put("userid", mFirebaseUser.getUid());
hashMap1.put("comment", "liked your comment");
hashMap1.put("postid", postId);
hashMap1.put("ispost", true);
hashMap1.put("notificationId", mNotificationId);
hashMap1.put("commentid", commentId);
hashMap1.put("seen", false);
hashMap1.put("type", "");
if (!mFirebaseUser.getUid().equals(userId)) {
FirebaseDatabase.getInstance().getReference("Notifications").child(userId).child(mNotificationId).setValue(hashMap1);
}
}
private void removeLike(String userId, String commentId) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Comments Liked").child(commentId).child(mFirebaseUser.getUid());
reference.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
String notificationId = dataSnapshot.child("notificationId").getValue(String.class);
if (notificationId != null) {
FirebaseDatabase.getInstance().getReference("Notifications").child(userId).child(notificationId).removeValue();
reference.removeValue();
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
private void dislikeComment(String commentId) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Comments Disliked").child(commentId).child(mFirebaseUser.getUid());
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("commentid", commentId);
hashMap.put("notificationId", mNotificationId);
hashMap.put("userid", mFirebaseUser.getUid());
reference.setValue(hashMap);
}
private void removeDislike(String commentId) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Comments Disliked").child(commentId).child(mFirebaseUser.getUid());
reference.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
reference.removeValue();
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
}
奇怪行為的原因是您在每次調用onBindViewHolder
注冊的ValueEventListener
對象。 每次新項目滾動到視圖中或更改其數據時,都會調用onBindViewHolder
方法。 由於您永遠不會取消注冊偵聽器,因此它們會繼續更新視圖,即使它們可能已經綁定到其他項目。
不要在onBindViewHolder
注冊任何監聽onBindViewHolder
。 使用您的適配器設置ValueEventListener
並在不再使用適配器時取消注冊它們。 在偵聽器中調用適配器的通知方法而不是直接更新視圖。 將 OnClickListeners 的注冊移動到您的 ViewHolder 中並使它們通用,這樣它們就不會綁定到特定項目。 onBindViewHolder
應該簡單地更新您的視圖。
所有更改都應該可以解決您的問題並使滾動更加流暢;-)
注釋適配器
public class CommentAdapter extends RecyclerView.Adapter<CommentAdapter.ViewHolder> {
private Context mContext;
private List<Comment> mCommentList;
private String mPostId;
private String mNotificationId;
private FirebaseUser mFirebaseUser;
public CommentAdapter(Context mContext, List<Item> items, String mPostId) {
this.items = items;
this.mPostId = mPostId;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.comment_item, parent, false);
return new CommentAdapter.ViewHolder(mContext, mPostId, view);
}
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
holder.update(items.get(position));
}
視圖持有人
public static class ViewHolder extends RecyclerView.ViewHolder {
private Item item;
public ViewHolder(Context context, String mPostId, View itemView) {
super(itemView);
// ...
// Register OnClickListeners here once for the view. Example:
icon.setOnClickListener(v -> {
if (item != null) {
Comment comment = item.getComment();
Intent intent = new Intent(mContext, ResponseActivity.class);
intent.putExtra("commentid", comment.getCommentid());
intent.putExtra("publisherid", comment.getPublisher());
intent.putExtra("postid", mPostId);
mContext.startActivity(intent);
}
});
// ...
}
public void update(Item item) {
this.item = item;
update(item.getComment());
update(item.getLikeStatus());
}
public void update(Comment comment) {
textControl.setText(comment.getText());
// ...
}
public void update(LikeStatus status) {
if (status.likes == 0) {
likeNumbersText.setVisibility(View.INVISIBLE);
} else {
likeNumbersText.setVisibility(View.VISIBLE);
likeNumbersText.setText(String.valueOf(likes));
}
if (status.dislikes == 0) {
dislikeNumbersText.setVisibility(View.INVISIBLE);
} else {
dislikeNumbersText.setVisibility(View.VISIBLE);
dislikesNumbersText.setText(String.valueOf(likes));
}
}
// ...
}
活動
DatabaseReference comments = FirebaseDatabase.getInstance().getReference("Comments").child(mPostId);
ChildEventListener childEventListener = new ChildEventListener() {
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
Comment comment = dataSnapshot.getValue(Comment.class);
Item item = getItemByCommentId(dataSnapshot.getKey());
item.setComment(comment);
mCommentAdatper.notifyItemChanged(comment.getPosition());
}
//...
};
comments.addChildEventListener(childEventListener);
DatabaseReference likes = FirebaseDatabase.getInstance().getReference("Comments Liked");
ChildEventListener childEventListener = new ChildEventListener() {
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
long likes = dataSnapshot.getChildrenCount();
String commendId = dataSnapshot.getKey();
Item item = getItemByCommentId(commendId);
Comment comment = item.getComment();
LikeStatus likeStatus = item.getLikeStatus();
likeStatus.likes = likes;
mCommentAdatper.notifyItemChanged(comment.getPosition());
}
// ...
};
likes.addChildEventListener(childEventListener);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.