Почему передача большого изображения через бандл считается плохой практикой
Что проверяют
Понимаете ли вы, что Bundle это не просто контейнер, а данные, которые копируются между процессами через Binder, и что у этого канала жёсткий лимит. По ответу видно, знаете ли вы, чем на самом деле ограничена передача данных между экранами.
Как отвечать
Bundle в Intent или в сохранённом состоянии сериализуется в Parcel и уходит через Binder. Буфер транзакции невелик, порядка мегабайта, и он общий на процесс. Превышение даёт TransactionTooLargeException, причём упасть может не ваша транзакция, а соседняя, которой не хватило места, поэтому воспроизводится это через раз.
Дальше про размер: картинка в памяти занимает ширину на высоту на число байтов на пиксель, для ARGB_8888 это четыре байта, то есть кадр с камеры весит десятки мегабайт и в буфер не влезет заведомо. Плюс это копия: одно изображение какое-то время существует сразу в двух процессах.
Как делают правильно:
- передавать
Uriили идентификатор, а картинку читать уже по нему; - класть файл в кэш-каталог приложения и передавать путь;
- наружу отдавать
content://через FileProvider с временным разрешением; - внутри одной Activity держать данные в общей
ViewModel, а в Compose поднимать состояние выше; - для загрузки и кэширования брать готовую библиотеку.
Где спотыкаются
Думают, что лимит проверяется на их собственном Bundle, и что чуть меньше мегабайта безопасно. Буфер делится на все транзакции процесса, запаса по факту нет, и падение зависит от того, что происходит рядом.
Сжимают картинку в массив байтов или в строку и считают вопрос закрытым. Кодирование в строку ещё и раздувает данные примерно на треть, а канал остаётся тем же самым.
Забывают про сохранение состояния. Там тот же Binder и тот же лимит, но получатель это системный процесс, и перегруженное состояние убивает приложение при повороте экрана или при возврате из фона, где связь с исходным вызовом уже не видна.