TransactionTooLargeException с FragmentStatePagerAdapter

Я написал приложение для чтения с помощью ViewPager с offscreenPageLimit по умолчанию 1 и FragmentStatePagerAdapter, в котором у меня

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

Здесь ComicFragment создается с indexкоторый может быть больше 2000, комикс с таким индексом будет загружен во фрагмент. ВsetRetainInstance по умолчанию false

Также во фрагменте я сохранил индекс и логическое значение transModeв saveInstanceState, так что когда пользователи пролистывают несколько страниц вперед и назад, они будут иметь страницу в том же состоянии, что и раньше. Также он будет поддерживать состояние при изменении конфигурации.

Проблема в том, что с каждым удаленным фрагментом из 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 КБ - это небольшой размер, но он накапливается в родительском фрагменте окна просмотра и его активности контейнера. Это означает, что при просмотре от индекса 1 до 1000 будет сохранено 800 КБ в состоянии родительского фрагмента. Здесь он достигает красной линии TransactionTooLargeException размером 1 МБ, когда я начинаю новое действие. (На самом деле, это исключение может произойти, даже если размер пакета составляет около 500 КБ)

Что еще хуже, пакет состояний в родительском фрагменте не выпущен. Я обнаружил, что с такой реализацией, если я просматриваю от 1 до 100, а затем обратно к 1, сохраненное состояние может быть применено к каждому фрагменту, но не освобождено, поскольку размер пакета состояний в родительском фрагменте удваивается как 160 КБ, а не 80 КБ.

Я почти ничего не вкладываю в комплект и не смею добавлять ничего большего, например сериализуемого, поскольку родной android:view_state потенциально достаточно, чтобы вызвать проблему.

Интересно, как следует улучшить реализацию, можно ли ее легко исправить или что-то более тяжелое, например, с использованием компонентов архитектуры Android, ViewPager2 или других зависимостей.

Обновить:

я пытался

  • view.isSaveFromParentEnabled = false в onViewCreated().

  • savedInstanceState?.clear() в конце onViewCreated().

  • android:saveEnabled="false" к представлениям с идентификатором, но сохранять их не нужно.

Из всех трех способов работает только 3-й.

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 раз без функционального компромисса.

0 ответов