RecyclerViewAdapter.getItemCount()有数据仍返回0解决方案
问题根因
你当前的空数据判断逻辑存在两个时序错误:
recyclerViewAdapter.startListening()是在onStart生命周期才执行,onCreateView运行时Firebase的数据监听还没启动,适配器本身还没开始拉取数据- Firebase数据库的数据拉取是异步网络操作,就算提前启动监听,同步执行的
onCreateView代码也不可能立刻拿到网络返回结果,此时调用getItemCount()必然返回0。等网络请求完成数据推送到适配器后,列表会自动刷新渲染,和你观察到的“延迟后第一条通知正常显示”的现象完全一致。
解决方案
不要在视图初始化阶段同步判断数据量,给适配器注册数据变化观察者,等数据集加载、变更完成后再触发空状态判断。
具体修改步骤
- 删除
onCreateView里原有同步判断getItemCount() == 0弹Toast的代码 - 适配器绑定到RecyclerView后,注册
AdapterDataObserver监听数据变化,在回调中执行空状态判断 - 在Fragment的
onDestroyView生命周期中注销观察者,避免内存泄漏
修改后的核心代码如下:
// 全局声明观察者对象,方便后续注销 private RecyclerView.AdapterDataObserver noticeDataObserver; @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_notice, container, false); recyclerView = view.findViewById(R.id.recycler_view); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); FirebaseRecyclerOptions<Notice> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<Notice>() .setQuery(FirebaseDatabase.getInstance().getReference() .child("Notice") .child(Values.schoolCode) .child(Values.student.getClass_txt()), Notice.class) .build(); recyclerViewAdapter = new RecyclerViewAdapter(firebaseRecyclerOptions); recyclerView.setAdapter(recyclerViewAdapter); // 注册数据变化监听 noticeDataObserver = new RecyclerView.AdapterDataObserver() { @Override public void onChanged() { super.onChanged(); // 数据加载/变更完成后再判断列表数据量 if (recyclerViewAdapter.getItemCount() == 0) { Toast.makeText(getContext(), "No Notice Found", Toast.LENGTH_SHORT).show(); } } }; recyclerViewAdapter.registerAdapterDataObserver(noticeDataObserver); return view; } @Override public void onStart() { super.onStart(); recyclerViewAdapter.startListening(); } @Override public void onStop() { super.onStop(); recyclerViewAdapter.stopListening(); } @Override public void onDestroyView() { super.onDestroyView(); // 注销监听防止内存泄漏 if (recyclerViewAdapter != null && noticeDataObserver != null) { recyclerViewAdapter.unregisterAdapterDataObserver(noticeDataObserver); } }
可选优化
如果不需要每次数据更新都触发空状态提示,可以加一个全局布尔标记位,仅在首次数据加载完成时做一次判断即可,避免重复弹出Toast。
注意:绝对不要使用固定时长的延迟等待数据加载,不同网络环境、数据量下的加载耗时差异极大,固定延迟会导致弱网场景下判断逻辑失效,出现空提示误判。
内容的提问来源于stack exchange,提问作者Aayush Shukla
相关产品推荐
相关产品推荐

