2021年8月21日土曜日

Activity遷移でTransactionTooLargeExceptionが発生する問題

Activityから別のActivityへ遷移した時、Bundleに保存されている情報がスタックされるのですが、Bundleにスタックできる情報量は1MB以下に制限されていて、1MBを超えるとTransactionTooLargeExceptionでアプリがクラッシュします。

ActivityのBundleだけでなく、FragmentのBundleの情報もスタックされる点に注意が必要です。(これだけが言いたかった)

正直なところ、「Activityの再生成メカニズムはまともに機能できていないのではないか?」と思う今日この頃です。再生成メカニズムというのは具体的には、Activityのライフサイクルの解説図面で言うところの「App process killed」のシーケンスです。

「App process killed」のシーケンスが実行されると、例えばシングルトンで保持しているインスタンス類は全てnullになってロストします。つまり、onCreateはその状態で再実行される可能性があるので、onCreateではシングルトンのデータ復旧処理などを記述しておく必要があります。

その設計思想通りに設計されたアプリが果たしてどの程度あるのか。

少なくとも、私は見たことがありません。

例えば、Google謹製のYouTubeアプリですら、初期状態からのリラン(プロセスリスタートと同等)をしています。

iOSにはこのような中途半端な復旧シーケンスは無くて、カーネルにアプリのプロセスが停止させられた場合、プロセスリスタートになります。

要は、以下が本来あるべき姿だと思います。

Activity Life cycleの本来あるべき姿(私見)

カーネルによりプロセスが停止された場合、アプリプロセスはリスタートで良いと思います。

むしろ、カーネルによる停止時にonDestroy実行保証してくれる方が重要だと思います。それが実現されれば、onDestroyでアプリプロセスがリスタートされた時に必要な情報をアプリ自身で記憶しておき、リスタート時にアプリ自身で復旧シーケンスを実行することが可能なので。

もう少し言ってしまうと、下図ぐらいシンプルにしてしまった方が良かったのではないかなと思います。

  • Start/Resume → onForegroundでまとめる
  • Pause/Stop → onBackgroundでまとめる
  • onRestart相当のものは無くても良い(必要ならonForegroundの引数でOK)
Androidのライフサイクルがこれぐらいシンプルだったら、そもそもTransactionTooLargeExceptionや前の記事で書いたNoSuchMethodExceptionなどというトラブルを生み出さなくても良かった筈。

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。

合理的ではないものを作りたい

ここ最近、実機版の東方VGSの開発が忙しくて、東方VGSの曲追加が滞っています。 東方VGS(実機版)のデザインを作りながら検討中。基本レトロUIベースですがシークバーはモダンに倣おうかな…とか pic.twitter.com/YOYprlDsYD — SUZUKI PLAN (...