如何获取Firebase Realtime Database嵌套节点子数据并解决空指针异常
问题根因及解决步骤
触发空指针的核心原因
mPosts列表中对应位置的Post对象本身为null,一般是从Posts节点下的ImagePosts、TextPosts拉取数据时,序列化失败直接把null存入了列表Post实体类的字段名、字段类型和数据库里存储的帖子字段不匹配,导致Firebase的getValue(Post.class)反序列化失败返回null,或者postedBy这类对应字段返回null- 仅查询了
Posts下的其中一个子节点,另一个子节点的帖子数据没有正常拉取填充到mPosts,出现数据错位
修复方案
第一步:添加空值校验避免崩溃
修改onBindViewHolder代码,提前拦截空值场景:
@Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { Post post = mPosts.get(position); // 提前校验post和关联字段是否为空 if (post == null || post.getPostedBy() == null) { // 可在此处设置默认占位展示,或直接跳过后续逻辑 return; } FirebaseDatabase.getInstance().getReference() .child("Users") .child(post.getPostedBy()) .addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { User user = snapshot.getValue(User.class); // 同步校验User对象是否为空 if (user == null) return; Picasso.get().load(user.getprofilepic()) .placeholder(R.drawable.placeholder_user) .into(holder.binding.profileImage); Picasso.get().load(user.getprofilepic()) .placeholder(R.drawable.placeholder_user) .into(holder.binding.profileImg); holder.binding.userName.setText(user.getName()); holder.binding.profession.setText(user.getProfession()); if (post.getPostDescription() != null) { holder.binding.postText.setText(Html.fromHtml("<b>"+user.getUsername() +"</b>" + " " + post.getPostDescription())); } } @Override public void onCancelled(@NonNull DatabaseError error) { } }); }
第二步:核对Post实体类定义
确保实体类满足Firebase序列化要求:
- 字段名必须和数据库中存储的字段完全一致,比如数据库中字段为
postedBy,实体类不能写成PostedBy或postBy - 必须包含无参的公开空构造方法,供Firebase反序列化调用
- 所有需要序列化的字段要么是public修饰符,要么有对应的公开get、set方法
第三步:检查数据拉取逻辑
分别监听ImagePosts和TextPosts两个节点,拉取到每个postId对应的数据后,先判断getValue(Post.class)返回值不为null,再添加到mPosts列表,每次数据更新后调用notifyDataSetChanged()刷新适配器。
内容的提问来源于stack exchange,提问作者Krishna Jindal
相关产品推荐
相关产品推荐

