Activity 保存的 android:support:fragments 越来越大,导致 TransactionTooLargeException

Posted

技术标签:

【中文标题】Activity 保存的 android:support:fragments 越来越大,导致 TransactionTooLargeException【英文标题】:android:support:fragments saved by Activity is getting larger and causing TransactionTooLargeException 【发布时间】:2019-12-26 08:10:42 【问题描述】:

我有一个控制几个片段的活动。默认片段为HomepageFragment。当替换到不同的 Fragment 时,我总是确保堆栈保持平坦 - 这意味着只有 HomepageFragment 留在堆栈中,并且在它的顶部是当前 Fragment。例如:

    HomepageFragment 打开的活动 需要替换为FragmentA - 一切都很好,因为HomepageFragment 是最后一个片段 现在堆栈是HomepageFragment -> FragmentA 需要替换为FragmentB - 首先弹出堆栈中的最后一个片段(fragmentA),而不是替换为FragmentB 现在堆栈是HomepageFragment -> FragmentB

在生产中,我看到很多 TransactionTooLargeException 崩溃。

我使用TooLargeTool 来跟踪问题的来源,我发现当我在活动中的片段之间切换时,SaveInstanceState 中有一个android:support:fragments 键,它变得越来越大(以指数方式)直到崩溃发生。

似乎即使从堆栈中弹出,有关原始交易的一些数据也会继续保存。

按照建议 here 删除它会导致 Activity 在被操作系统杀死后无法正常恢复。

我的压平堆栈的方法有问题吗? 有更好的方法吗? android:support:fragments下到底保存了哪些数据?

注意:我没有为这些片段设置任何参数。此外,他们在他们的 saveInstanceState 包中保存了非常小的数据。

谢谢!

【问题讨论】:

***.com/a/52716351/4390987 ***.com/questions/13093677/… java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 558780 bytes when navigating between fragment的可能重复 @ManojPerumarath 我没有将任何数据传输到这些片段。我的情况完全不同,是由于 ACTIVITY 中的一些键变得越来越大,只有在大约 20 个片段之后它才大到足以崩溃。请删除重复项。 也许您正在保存位图?也许您正在使用像 ImageCropper 这样的 aibraey,它将位图持久保存到 Bundle? 【参考方案1】:

我在我的 Activity 中通过 supportFragmentManager.registerFragmentLifecycleCallbacks 进行了一些调试,覆盖并在 onFragmentSaveInstanceState 中设置断点。

看来android:support:fragments Bundle 包含

    来自 ViewModel 的已保存状态 (SavedStateHandle) 后栈中 Fragments 的导航参数

在我的例子中,罪魁祸首是一个自定义 Parcelable,它可以增长到数百 kB。如果有多个在后台堆栈和 SavedStateHandles 中,应用程序将超过 1MB 阈值并崩溃。

我通过仅传递该 Parcelable 的 ID 并从我的存储库加载它来解决问题。性能略有下降,但不再崩溃。

【讨论】:

以上是关于Activity 保存的 android:support:fragments 越来越大,导致 TransactionTooLargeException的主要内容,如果未能解决你的问题,请参考以下文章

TextInputLayout

activity状态保存与恢复

Android总结 - Activity任务和返回栈保存Activity的状态

Android基础部分再学习---activity的状态保存

Android处理运行时变更保存数据状态恢复Activity

Android组件系列-----Activity保存状态