Android Fragment调用RecyclerView.setHasFixedSize空指针异常排查
问题根因
抛出空指针是两个错误直接导致的:
- 控件ID不匹配:
fragment_communities.xml中RecyclerView设置的id是re,但Java代码中查找控件时传入的id是R.id.userList,找不到对应控件自然返回null - 控件查找方式错误:Fragment中查找自身布局内的控件,必须使用inflate生成的Fragment根View调用
findViewById(),你调用getActivity().findViewById()时,Fragment的布局还没挂载到Activity的视图树上,也会导致查找结果为null
除此之外还有两个隐藏问题,就算修复空指针也无法正常展示列表:
- Firestore数据拉取完成、向集合添加完数据后,没有通知适配器刷新,列表不会自动更新新加入的数据
- 直接强转
documentSnapshot.getData()为Communities类型会触发类型转换异常,该方法返回值是Map<String, Object>类型,必须用Firestore自带的toObject()方法做实体类转换。
修复方案
- 统一布局与代码中的控件ID,建议把
fragment_communities.xml里的RecyclerView id改为userList,同时把写死的固定宽高改为match_parent,避免不同分辨率设备上布局错位,修改后的RecyclerView节点如下:
<androidx.recyclerview.widget.RecyclerView android:id="@+id/userList" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginStart="2dp" android:layout_marginTop="2dp" android:layout_marginEnd="2dp" android:layout_marginBottom="2dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
- 修正Fragment中的控件查找、数据转换、列表刷新逻辑,修正后的
onCreateView代码如下:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { db = FirebaseFirestore.getInstance(); View view = inflater.inflate(R.layout.fragment_communities, container, false); // 必须用Fragment自身inflate出的view查找布局内控件 recyclerView = view.findViewById(R.id.userList); recyclerView.setHasFixedSize(true); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); communities = new ArrayList<>(); recycleViewAdapter = new RecycleViewAdapter(getContext(),communities); recyclerView.setAdapter(recycleViewAdapter); db.collection("Communities").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() { @Override public void onComplete(@NonNull Task<QuerySnapshot> task) { if(task.isSuccessful()){ communities.clear(); // 清空旧数据避免重复加载出现重复项 for(QueryDocumentSnapshot documentSnapshot : task.getResult()){ // 调用toObject方法做实体类映射,禁止直接强转getData返回值 Communities community = documentSnapshot.toObject(Communities.class); communities.add(community); } // 数据全部加载完成后通知适配器刷新UI recycleViewAdapter.notifyDataSetChanged(); } } }); return view; }
- 检查你的
Communities实体类,必须保证存在无参构造方法,以及对应字段的public getter方法,否则Firestore无法正常完成字段映射。
内容的提问来源于stack exchange,提问作者Gabriel Falieri
相关产品推荐
相关产品推荐

