RecyclerView嵌套场景下ImageView空指针异常排查求助
解决嵌套RecyclerView中DeliverableView的ImageView空指针异常
我看了你贴的代码,问题出在DeliverableView这个自定义View的初始化流程上——你把布局加载和ButterKnife绑定放在了onFinishInflate()方法里,但这个方法的执行时机晚于你调用populate()的时间,导致控件还没完成绑定就去赋值,自然会抛出空指针异常。
核心原因
onFinishInflate()是在View及其所有子View都从XML解析完成后才会触发的回调,但你的DeliverableAdapter在ViewHolder的bindModel()方法里,会立即调用deliverableView.populate(deliverable),这时候onFinishInflate()可能还没执行,控件都还没被绑定,所以iv_deliverable_image会是null。
方案1:调整初始化时机(推荐)
把布局加载和ButterKnife绑定移到构造方法里,确保View实例化时就完成控件初始化,这样后续调用populate()时所有控件都已经就绪:
修改后的DeliverableView代码:
public class DeliverableView extends ConstraintLayout { @BindView(R.id.iv_deliverable_image) ImageView iv_deliverable_image; @BindView(R.id.tv_deliverable_name) TextView tv_deliverable_name; @BindView(R.id.tv_deliverable_size) TextView tv_deliverable_size; @BindView(R.id.tv_deliverable_quantity) TextView tv_deliverable_quantity; @BindView(R.id.tv_deliverable_amount) TextView tv_deliverable_amount; public DeliverableView(Context context) { super(context); init(); } public DeliverableView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public DeliverableView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } // 统一初始化逻辑 private void init() { // 加载布局并添加到当前ConstraintLayout中 LayoutInflater.from(getContext()).inflate(R.layout.layout_componet_deliverable, this, true); // 立即绑定ButterKnife ButterKnife.bind(this); } public void populate(Entity deliverable) { // 加个判空保险,防止极端情况 if (iv_deliverable_image == null) return; Glide.with(getContext()) .load(StringUtil.trimUrlByHeight(deliverable.attributes.image_url, 60)) .into(iv_deliverable_image); tv_deliverable_quantity.setText(String.valueOf(deliverable.attributes.count)); tv_deliverable_name.setText(deliverable.attributes.name); tv_deliverable_size.setText(deliverable.attributes.size); tv_deliverable_amount.setText(StringUtil.getDisplayedBill(deliverable.attributes.amount_in_cents * deliverable.attributes.count)); } // 移除原来的onFinishInflate重写,不需要了 }
方案2:延迟调用populate(备选)
如果坚持要在onFinishInflate()里做绑定,可以给DeliverableView加一个初始化完成的回调,确保populate()在控件绑定后执行:
- 修改DeliverableView:
public class DeliverableView extends ConstraintLayout { // ...原有控件定义 private OnViewInitializedListener initListener; // 定义初始化完成的回调接口 public interface OnViewInitializedListener { void onViewReady(); } public void setOnViewInitializedListener(OnViewInitializedListener listener) { this.initListener = listener; } // ...原有构造方法 @Override protected void onFinishInflate() { super.onFinishInflate(); View.inflate(getContext(), R.layout.layout_componet_deliverable, this); ButterKnife.bind(this); // 初始化完成后通知外部 if (initListener != null) { initListener.onViewReady(); } } // ...原有populate方法 }
- 修改DeliverableAdapter的ViewHolder:
class ViewHolderDeliverable extends RecyclerView.ViewHolder { @BindView(R.id.deliverableView) DeliverableView deliverableView; ViewHolderDeliverable(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } void bindModel(final Entity deliverable) { deliverableView.setOnViewInitializedListener(new DeliverableView.OnViewInitializedListener() { @Override public void onViewReady() { deliverableView.populate(deliverable); } }); } }
额外检查点
最后再确认两个细节,避免其他潜在问题:
- 检查
layout_componet_deliverable.xml中的ImageView id是否确实是iv_deliverable_image,没有拼写错误; - 确认ButterKnife依赖已正确引入,版本和项目的AndroidX/支持库适配。
内容的提问来源于stack exchange,提问作者rereh
相关产品推荐
相关产品推荐

