为何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
相关产品推荐
相关产品推荐

