无法获取Firebase生成的Post密钥以添加并展示子级评论问题
解决Firebase Realtime Database帖子评论的两个核心问题
看起来你已经搞定了帖子详情页的基础展示,现在卡在评论的添加和展示环节,我来帮你一步步梳理解决:
一、获取帖子密钥并添加评论到对应子节点
首先你已经通过Intent拿到了帖子ID(也就是Firebase生成的push密钥):String id = intent.getStringExtra("post_ID");,这个id就是定位帖子的关键标识,接下来用它来关联评论节点:
1. 补全Firebase初始化与评论写入逻辑
先在onCreate里初始化用户实例,避免空指针:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_show_the_post); ButterKnife.bind(this); dialog = new Dialog(this); intent = getIntent(); // 初始化Firebase用户和数据库引用 mAuth = FirebaseAuth.getInstance().getCurrentUser(); dbRef = FirebaseDatabase.getInstance().getReference(); getDataFromIntent(); }
然后修改ShowCommentDialog里的btnDone点击事件,把评论写入对应帖子的Comments子节点:
btnDone.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(mAuth == null){ Toasty.error(ShowThePost.this, "请先登录再评论", Toast.LENGTH_SHORT).show(); return; } final String category = intent.getStringExtra("category"); String postId = intent.getStringExtra("post_ID"); // 拿到目标帖子的密钥 String Notes = txtNotes.getText().toString().trim(); String SuggestedPrice = txtSuggestprice.getText().toString().trim(); // 校验输入完整性 if(Notes.isEmpty() || SuggestedPrice.isEmpty()){ Toasty.warning(ShowThePost.this, "请填写完整评论信息", Toast.LENGTH_SHORT).show(); return; } String UserID = mAuth.getUid(); String UserProfilePic = mAuth.getPhotoUrl() != null ? mAuth.getPhotoUrl().toString() : ""; String UserName = mAuth.getDisplayName() != null ? mAuth.getDisplayName() : "匿名用户"; // 生成格式化的评论时间 String commentDate = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault()).format(new Date()); CommentsList commentsList = new CommentsList(); commentsList.setUserID(UserID); commentsList.setUserProfilePicture(UserProfilePic); commentsList.setCommentDescription(Notes); commentsList.setCommentSuggestPrice(SuggestedPrice); commentsList.setCommentDate(commentDate); // 定位到帖子的Comments节点,push生成评论的唯一ID并写入数据 dbRef.child("Posts").child(category).child(postId).child("Comments") .push().setValue(commentsList) .addOnSuccessListener(unused -> { dialog.dismiss(); Toasty.success(ShowThePost.this, "评论发布成功", Toast.LENGTH_SHORT).show(); }) .addOnFailureListener(e -> Toasty.error(ShowThePost.this, "发布失败:"+e.getMessage(), Toast.LENGTH_SHORT).show() ); } });
2. 确认适配器传递了正确的帖子密钥
确保你的BooksAdapter在跳转时,确实把帖子的Firebase密钥传给了ShowThePost,比如在onBindViewHolder中:
@Override public void onBindViewHolder(@NonNull final BooksItemsHolder holder, int position) { final BooksLists book = listy.get(position); // 其他数据绑定逻辑... holder.itemView.setOnClickListener(v -> { Intent intent = new Intent(mContext, ShowThePost.class); intent.putExtra("post_ID", book.getPostId()); // 传递帖子的Firebase密钥 intent.putExtra("post_Title", book.getPostTitle()); // 其他需要传递的字段... mContext.startActivity(intent); }); }
这里的book.getPostId()是你在BooksLists模型类中存储的帖子密钥字段,要保证从Firebase读取帖子时,把每个帖子的key也保存到模型里。
二、在帖子详情页展示评论
接下来实现评论列表的展示,需要添加RecyclerView来加载评论:
1. 修改布局文件activity_show_the_post.xml
在现有布局下方添加评论RecyclerView:
<androidx.recyclerview.widget.RecyclerView android:id="@+id/rv_comments" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
2. 创建评论适配器与布局
假设你的CommentsList模型类字段已完善,创建CommentsAdapter:
public class CommentsAdapter extends RecyclerView.Adapter<CommentsAdapter.CommentViewHolder> { private List<CommentsList> commentList; private Context context; public CommentsAdapter(List<CommentsList> commentList, Context context) { this.commentList = commentList; this.context = context; } @NonNull @Override public CommentViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_comment, parent, false); return new CommentViewHolder(view); } @Override public void onBindViewHolder(@NonNull CommentViewHolder holder, int position) { CommentsList comment = commentList.get(position); holder.tvUserName.setText(comment.getUserName()); holder.tvCommentDate.setText(comment.getCommentDate()); holder.tvCommentDesc.setText(comment.getCommentDescription()); holder.tvSuggestedPrice.setText(comment.getCommentSuggestPrice()); // 加载用户头像 if(!comment.getUserProfilePicture().isEmpty()){ GlideApp.with(context) .load(comment.getUserProfilePicture()) .into(holder.civUserProfile); } } @Override public int getItemCount() { return commentList.size(); } public static class CommentViewHolder extends RecyclerView.ViewHolder { CircularImageView civUserProfile; TextView tvUserName, tvCommentDate, tvCommentDesc, tvSuggestedPrice; public CommentViewHolder(@NonNull View itemView) { super(itemView); civUserProfile = itemView.findViewById(R.id.civ_comment_profile); tvUserName = itemView.findViewById(R.id.tv_comment_username); tvCommentDate = itemView.findViewById(R.id.tv_comment_date); tvCommentDesc = itemView.findViewById(R.id.tv_comment_desc); tvSuggestedPrice = itemView.findViewById(R.id.tv_comment_suggest_price); } } }
对应的item_comment.xml布局可以根据需求设计,包含用户头像、用户名、评论时间、内容和建议价格等控件。
3. 在ShowThePost中监听评论节点并加载数据
初始化评论RecyclerView,添加Firebase监听实时更新评论:
// 新增成员变量 private RecyclerView rvComments; private CommentsAdapter commentsAdapter; private List<CommentsList> commentList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_show_the_post); ButterKnife.bind(this); dialog = new Dialog(this); intent = getIntent(); mAuth = FirebaseAuth.getInstance().getCurrentUser(); dbRef = FirebaseDatabase.getInstance().getReference(); // 初始化评论RecyclerView rvComments = findViewById(R.id.rv_comments); rvComments.setLayoutManager(new LinearLayoutManager(this)); commentsAdapter = new CommentsAdapter(commentList, this); rvComments.setAdapter(commentsAdapter); getDataFromIntent(); loadComments(); // 加载评论列表 } // 加载并监听评论变化 private void loadComments(){ String category = intent.getStringExtra("category"); String postId = intent.getStringExtra("post_ID"); dbRef.child("Posts").child(category).child(postId).child("Comments") .addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { commentList.clear(); for(DataSnapshot commentSnapshot : snapshot.getChildren()){ CommentsList comment = commentSnapshot.getValue(CommentsList.class); commentList.add(comment); } commentsAdapter.notifyDataSetChanged(); // 无评论时可添加空状态提示 } @Override public void onCancelled(@NonNull DatabaseError error) { Toasty.error(ShowThePost.this, "加载评论失败:"+error.getMessage(), Toast.LENGTH_SHORT).show(); } }); }
这样当有新评论发布时,RecyclerView会自动更新展示最新内容。
额外注意事项
- 开发阶段可暂时设置Firebase数据库规则为公开读写,上线后要修改为基于用户权限的规则
- 确保
CommentsList模型类有无参构造函数和完整的getter/setter,否则Firebase无法反序列化数据 - 处理用户未登录的场景,比如点击评论按钮时先判断登录状态
内容的提问来源于stack exchange,提问作者Amelie
相关产品推荐
相关产品推荐

