如何从ViewPager2访问RecyclerView 点击Tab触发空指针异常如何解决
解决方案
核心问题除了你排查出的时机差之外,还有一个逻辑误区:子Fragment的视图是独立于父Fragment的视图树的,你在父Fragment中调用findViewById查找子Fragment内部的RecyclerView本身不符合Android视图隔离规则,滑动时能正常运行属于巧合。
下面提供3种可行的修复方案:
方案1:开启全量预加载(改动最小,适合当前3个Tab的场景)
ViewPager2默认仅缓存当前页和左右相邻各1页,你总共有3个Tab,直接设置离屏页面缓存数为2,让所有页面在初始化时就完成创建,从根源上消除时机差。
在onCreateView中设置适配器后添加一行代码即可:
pager2.setOffscreenPageLimit(2);
方案2:逻辑下沉到子Fragment(架构最优,推荐长期使用)
调整职责划分,每个子Fragment自己负责自身视图的初始化和数据填充,不要在父Fragment跨层级操作子页面控件:
- 给每个子Fragment新增接收数据的公共方法,比如
setData(Collatz collatz),把需要展示的列表数据传入子Fragment内部存储 - 子Fragment在自身的
onViewCreated生命周期中初始化RecyclerView,再用之前传入的数据完成列表填充 - 父Fragment的
fillFragment方法仅负责给对应位置的子Fragment传递数据,不需要操作任何控件
这种方案完全符合Android开发规范,不会再出现控件查找失败、时机异常的问题。
方案3:增加空校验兼容现有逻辑
如果暂时不想调整现有架构,可以在访问控件前增加判空逻辑,避免空指针崩溃:
在fillFragment中每次查找RecyclerView之后,先判断对象是否为空,非空才执行后续配置操作:
mRecyclerView = (RecyclerView) myFragment.findViewById(R.id.recycler_view); // 增加空校验,未初始化则直接跳过本次填充 if (mRecyclerView == null) return; mRecyclerView.setHasFixedSize(false); // 剩余原有逻辑
同时可以把待填充的数据先缓存到全局变量,等后续页面切换回调触发时再重新执行填充。
内容的提问来源于stack exchange,提问作者Erick Sorto
相关产品推荐
相关产品推荐

