You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何getPostId()在部分调用场景中返回null引发NullPointerException?

问题分析与解决方案

问题现象

调用addNotification(pst.getPublisher(), pst.getPostId())时,getPostId()返回null,但getPublisher()能正常取值。但在以下代码中:

isLikes(pst.getPostid(),holder.like);
mrLikes(holder.likes,pst.getPostid());
getComments(pst.getPostid(),holder.comments);

getPostid()能返回正确值且运行正常。另外,调用editPost(pst.getPostid())以及postimage的setOnClickListener时,getPostid()同样返回null,尝试在点击事件内重新获取pst = mpost.get(position)也无效。

核心原因

RecyclerView的ViewHolder复用机制导致变量引用失效:你在onBindViewHolder中使用成员变量pst存储当前Post对象,当列表滚动时,ViewHolder会被复用给新的列表项,pst会被覆盖为新的Post对象。当之前的点击事件触发时,pst已经指向了其他位置的对象,甚至可能是已被回收的对象,从而导致getPostid()返回null。

解决方案

方案1:用final变量绑定当前Post对象

在onBindViewHolder内部,将当前位置的Post对象赋值给一个final变量,确保点击事件引用的是绑定ViewHolder时的原始对象:

public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
    // 用final变量保存当前列表项的Post对象
    final Post currentPost = mpost.get(position);
    pst = currentPost;
    if(mContext==null){
        return;
    }
    // 原有UI绑定逻辑不变
    Glide.with(mContext).load(currentPost.getPostimage()).apply(new RequestOptions().placeholder(R.drawable.praceholder)).into(holder.postimage);
    holder.description.setText(currentPost.getDescription());
    holder.catagory.setText(currentPost.getCatagory());
    holder.location.setText(currentPost.getLocation());
    
    publisherinfo(holder.image_profile,holder.uname,holder.publisher,currentPost.getPublisher());
    isLikes(currentPost.getPostid(),holder.like);
    mrLikes(holder.likes,currentPost.getPostid());
    getComments(currentPost.getPostid(),holder.comments);

    holder.like.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if(holder.like.getTag().equals("like")){
                FirebaseDatabase.getInstance().getReference().child("likes").child(currentPost.getPostid()).child(firebaseUser.getUid()).setValue(true);
                addNotifications(currentPost.getPublisher(), currentPost.getPostid());
            }else{
                FirebaseDatabase.getInstance().getReference().child("likes").child(currentPost.getPostid()).child(firebaseUser.getUid()).removeValue();
            }
        }
    });

    holder.more.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            PopupMenu popupMenu = new PopupMenu(mContext,view);
            popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem menuItem) {
                    switch (menuItem.getItemId()){
                        case R.id.edit:
                            editPost(currentPost.getPostid());
                            return true;
                        case R.id.delete:
                            FirebaseDatabase.getInstance().getReference("Posts").child(currentPost.getPostid()).removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
                                @Override
                                public void onComplete(@NonNull Task<Void> task) {
                                    if(task.isSuccessful()){
                                        Toast.makeText(mContext,"Deleted",Toast.LENGTH_SHORT).show();
                                    }
                                }
                            });
                            return true;
                        case R.id.report:
                            Toast.makeText(mContext,"reported",Toast.LENGTH_SHORT).show();
                            return true;
                        default:
                            return false;
                    }
                }
            });
            // 补充原代码遗漏的弹窗显示方法
            popupMenu.show();
        }
    });

    holder.postimage.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            SharedPreferences.Editor editor = mContext.getSharedPreferences("PREFS",Context.MODE_PRIVATE).edit();
            editor.putString("postid",currentPost.getPostid());
            editor.apply();
            ((FragmentActivity)mContext).getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,new PostDetailsFragment()).commit();
        }
    });
}

方案2:将PostId绑定到ViewHolder的Tag

把PostId直接存储到ViewHolder的根View标签中,点击事件时从Tag中取出:

public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
    pst = mpost.get(position);
    if(mContext==null){
        return;
    }
    // 将postId绑定到ViewHolder根View的Tag
    holder.itemView.setTag(pst.getPostid());
    
    // 原有UI绑定逻辑不变
    Glide.with(mContext).load(pst.getPostimage()).apply(new RequestOptions().placeholder(R.drawable.praceholder)).into(holder.postimage);
    // ... 其他UI赋值代码 ...

    holder.like.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            String postId = (String) holder.itemView.getTag();
            if(holder.like.getTag().equals("like")){
                FirebaseDatabase.getInstance().getReference().child("likes").child(postId).child(firebaseUser.getUid()).setValue(true);
                addNotifications(pst.getPublisher(), postId);
            }else{
                FirebaseDatabase.getInstance().getReference().child("likes").child(postId).child(firebaseUser.getUid()).removeValue();
            }
        }
    });

    // 其他点击事件同理,均从holder.itemView.getTag()获取postId
}

额外排查点

检查Post实体类的方法名拼写:代码中同时出现了getPostId()和getPostid()两种写法,如果实体类中定义的方法名与调用时不一致,会直接返回null,请确保方法名完全匹配。

内容的提问来源于stack exchange,提问作者ton_fako

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 10:15:33