如何在RecyclerView加载完成后执行指定方法,避免空指针异常?
问题原因
你在onStart中调用loadRecyclerView()后直接执行取值逻辑时,RecyclerView 还未完成布局测量、ViewHolder 创建绑定的流程,对应position的ViewHolder还未初始化,因此findViewHolderForAdapterPosition()返回null,触发空指针异常。按钮点击时正常是因为此时界面已经完成渲染,ViewHolder已经创建完成。
解决方案
方案1(推荐):在RecyclerView.Adapter的onBindViewHolder中处理
这是最符合RecyclerView设计规范的实现方式,不受条目可见性、回收复用逻辑影响,不会出现空指针问题:
@Override public void onBindViewHolder(@NonNull YourViewHolder holder, int position) { // 原有绑定逻辑 EditText editText = holder.itemView.findViewById(R.id.editText); if (position == 6) { // 第7个条目(position从0开始)设置为密码输入类型 editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); } else { // 其他位置重置为默认输入类型,避免ViewHolder复用导致的样式混乱 editText.setInputType(InputType.TYPE_CLASS_TEXT); } }
方案2:监听RecyclerView布局完成回调
如果你确实需要在Adapter外部执行设置逻辑,可以通过布局监听或者post任务的方式,等待RecyclerView渲染完成后再执行:
方式A:使用View.post()
post的任务会在RecyclerView完成测量、布局、渲染后自动执行:
// 调用loadRecyclerView()后执行以下代码 recyclerView.post(() -> { RecyclerView.ViewHolder holder = recyclerView.findViewHolderForAdapterPosition(6); // 必须加非空判断:如果position6的条目不在当前可视区域,仍会返回null if (holder != null) { ((EditText)holder.itemView.findViewById(R.id.editText)) .setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); } });
方式B:使用OnGlobalLayoutListener监听布局完成
recyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { RecyclerView.ViewHolder holder = recyclerView.findViewHolderForAdapterPosition(6); if (holder != null) { ((EditText)holder.itemView.findViewById(R.id.editText)) .setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); } // 移除监听避免重复触发 recyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this); } });
注意:所有外部修改Item属性的方案,都需要处理ViewHolder回收的问题,如果对应position的条目滑出可视区域后再滑回,你设置的属性会被重置,因此优先选择方案1在Adapter内部处理。
内容的提问来源于stack exchange,提问作者Matan Shalel
相关产品推荐
相关产品推荐

