Fragment中已绑定适配器的RecyclerView仍报“No adapter attached; skipping layout”错误的原因排查
嘿,我来帮你捋捋这个让人头疼的问题——明明已经给RecyclerView绑了适配器,却还是弹出“No adapter attached; skipping layout”的错误,结合你用NavGraph切换Fragment的场景,大概率是这些环节出了问题:
异步加载导致的绑定时机滞后
如果你是在网络请求、数据库查询这类异步操作完成后才给RecyclerView设置适配器,那RecyclerView第一次执行布局测量的时候,适配器还没到位,自然会报错。虽然之后异步完成你绑定了适配器,日志也显示“已绑定”,但错误已经在之前的布局阶段触发了。
解决思路:先给RecyclerView设置一个空适配器占位,比如recyclerView.adapter = YourAdapter(emptyList()),等数据加载完成后,再通过adapter.submitList(newData)或者更新数据源后调用notifyDataSetChanged()来刷新,这样第一次布局时就有适配器了。RecyclerView实例找错了!
你在Fragment里初始化RecyclerView的时候,是不是用对了findViewById的上下文?比如在onViewCreated()里,必须用view.findViewById(R.id.your_recyclerview),要是不小心用了getActivity().findViewById(),很可能拿到的是Activity布局里的其他View,甚至是null。这时候你以为给RecyclerView绑了适配器,实际上是绑到了一个不存在的对象上,真正布局的那个RecyclerView根本没适配器,自然报错。
排查小技巧:加个日志打印recyclerView对象,看看是不是null,或者打印它的ID,确认和布局文件里的ID一致。Fragment生命周期与NavGraph的切换时机冲突
用NavGraph切换Fragment时,有没有可能Fragment还没完全附着到Activity上,就开始初始化RecyclerView了?虽然你试过onViewCreated()和onCreateView(),但也可以试试把适配器绑定的代码移到onStart()里(不过不建议随便改生命周期顺序,先排查前面的点)。另外,也可以检查下NavGraph里的Fragment启动模式,会不会导致Fragment实例重复创建,出现多个RecyclerView实例的情况。适配器赋值环节的隐性问题
有没有可能你设置适配器的代码没真正执行到?比如被某个条件分支跳过了?或者你创建了适配器对象,但没把它赋值给recyclerView.adapter?比如写成了val adapter = YourAdapter(data)但没写recyclerView.adapter = adapter,这种低级错误有时候也会犯,仔细检查下代码逻辑。布局文件的坑
看看RecyclerView在布局里的设置:是不是宽高设成了wrap_content但数据源为空时没占位?或者父布局的约束没设置对,导致RecyclerView第一次布局时尺寸为0,系统直接跳过布局触发错误?比如在ConstraintLayout里,要是没给RecyclerView设置上下左右的约束,它可能根本不会显示,同时触发这个错误。
备注:内容来源于stack exchange,提问作者Euan Hall

