4

我使用默认为 1 的 ViewPager 和 FragmentStatePagerAdapter 编写了一个阅读器应用程序offscreenPageLimit,其中我有

override fun getItem(position: Int) = ComicFragment.newInstance(index = position + 1)

这里创建了一个index大于 2000 的 ComicFragment,具有此类索引的漫画将被加载到片段中。setRetainInstance默认为false

同样在片段中,我transMode在 savedInstanceState 中保存了索引和布尔值,这样当用户来回滑动几页时,他们将拥有与原来相同的页面状态。它还将维护配置更改的状态。

问题是,随着从TooLargeTool中滑走的每个片段,

D/TooLargeTool: ComicFragment.onSaveInstanceState wrote: Bundle126358192 contains 4 keys and measures 0.8 KB when serialized as a Parcel
    * androidx.lifecycle.BundlableSavedStateRegistry.key = 0.1 KB
    * transMode = 0.0 KB
    * android:user_visible_hint = 0.1 KB
    * android:view_state = 0.6 KB
    * fragment arguments = Bundle247579945 contains 1 keys and measures 0.0 KB when serialized as a Parcel
    * index = 0.0 KB

0.8 KB 不算大,但是在viewpager 的父fragment 和它的容器activity 中积累起来的。这意味着从索引 1 浏览到 1000 时,将有 800 KB 保存在父片段的状态。当我开始一个新活动时,它到达了 1MB TransactionTooLargeException 的红线。(实际上,即使捆绑包大约 500KB 也可能发生此异常)

更糟糕的是父片段中的状态包没有释放。我发现通过这样的实现,如果我从 1 浏览到 100 然后反向返回到 1,保存的状态可以应用于每个片段但不会释放,因为父片段中状态包的大小加倍为 160 KB 而不是 80 KB。

我几乎没有在包中放任何东西,也不敢添加任何更大的东西,比如可序列化的,因为本机android:view_state可能足以引起问题。

我想知道应该如何改进实现,是否可以轻松修复,或者更重的东西,例如使用 Android 架构组件、ViewPager2 或其他依赖项。

更新:

我试过了

  • view.isSaveFromParentEnabled = falseonViewCreated().

  • savedInstanceState?.clear()在结束时onViewCreated()

  • android:saveEnabled="false"到那些具有 id 的视图,但不需要保存。

在这三种方式中,只有第三种有效。

D/TooLargeTool: ComicFragment.onSaveInstanceState wrote: Bundle242738747 contains 1 keys and measures 0.1 KB when serialized as a Parcel
    * androidx.lifecycle.BundlableSavedStateRegistry.key = 0.1 KB
    * transMode = 0.0 KB
    * fragment arguments = Bundle232075608 contains 1 keys and measures 0.0 KB when serialized as a Parcel
    * index = 0.0 KB

android:view_state已完全消除,因为我没有任何需要保持状态的视图(EditText、ToggleButton)。

这个问题还没有完全解决,但我相信现在异常的机会已经降低了 8 倍,而不会影响功能。

4

0 回答 0