Android:Activity销毁时触发StaleDataException崩溃(仅三星设备)
StaleDataException(仅三星特定设备) 看起来你遇到了一个很棘手的设备特定崩溃问题——只在两款三星Galaxy设备(SM-G950F [API 26]、Galaxy J7 [API 23])上,CreatePostActivityMod销毁时触发崩溃,其余测试设备完全正常。让我帮你拆解下问题并给出可行的解决方案:
问题核心
从你提供的堆栈信息来看,崩溃的根源是:
android.database.StaleDataException: Attempted to access a cursor after it has been closed.
具体触发路径是:Activity销毁时,系统的无障碍服务(Accessibility)尝试初始化RecyclerView的无障碍节点信息,此时你的CustomGalleryAdapter的getItemCount()方法调用了已经被关闭的Cursor的getCount(),直接抛出异常。
为什么只在三星设备出现?大概率是三星定制的Android系统中,无障碍服务的触发时机和原生/其他厂商系统有差异——在Activity销毁、Cursor已经被关闭后,三星系统仍然会尝试访问RecyclerView的无障碍数据,而其他设备在这个阶段已经不会执行这类操作。
修复方案
这里有几个递进的修复思路,你可以根据自己的代码情况选择:
1. 给Adapter的Cursor访问加安全校验
最直接的方式是修改CustomGalleryAdapter的getItemCount()方法,先检查Cursor是否有效(未关闭且不为null),再执行计数操作:
@Override public int getItemCount() { // 先判断Cursor状态,避免访问已关闭的Cursor if (mCursor == null || mCursor.isClosed()) { return 0; } return mCursor.getCount(); }
同时,要确保Adapter的Cursor切换逻辑是安全的,比如在swapCursor方法里正确处理旧Cursor的关闭:
public void swapCursor(Cursor newCursor) { if (mCursor != null && mCursor != newCursor) { mCursor.close(); } mCursor = newCursor; notifyDataSetChanged(); }
2. 在Activity销毁时提前解绑Adapter
在CreatePostActivityMod的onDestroy方法中,先把RecyclerView的Adapter置为null,再执行Cursor关闭等销毁操作,从根源上避免无障碍服务访问到持有无效Cursor的Adapter:
@Override protected void onDestroy() { // 先清空RecyclerView的Adapter,切断无效Cursor的引用 if (mGalleryRecyclerView != null) { mGalleryRecyclerView.setAdapter(null); } // 再关闭Cursor、执行其他清理逻辑 if (mGalleryCursor != null) { mGalleryCursor.close(); } super.onDestroy(); }
3. 临时禁用RecyclerView的无障碍支持(不推荐)
如果前两个方案都无法解决问题,可以临时禁用RecyclerView的无障碍功能,但这会影响使用无障碍服务的用户体验,除非万不得已不要用:
mGalleryRecyclerView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
验证建议
修复完成后,重点在出问题的两款三星设备上测试Activity销毁的场景(比如按返回键退出、切换后台后杀死进程),确认崩溃不再复现。
内容的提问来源于stack exchange,提问作者Massimo Baldrighi

