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