Android端末のメモリによってライフサイクルが変わる

Android, ライフサイクル, 端末依存

村瀬です。

今回は新卒向けネイティブアプリ研修のAndroid実習で使用するコロコロカービィ風アプリを準備していたときに直面した問題について紹介いたします。

事象

AQUOS(SH-01K)でコロコロカービィをバックグラウンドから再起動したときと、Pixel 3aで実行したときの挙動が異なる

demo-aquos-resize.gif demo-pixel-resize.gif

AQUOS(左)の場合、バッググラウンドから再度起動させるとカービィは中央に戻っており、途中からではなく初回起動と同じ挙動になっています。
一方、Pixel 3a(右)の場合はバッググラウンドから再度起動させるとカービィの位置は変わっておらず、途中から動作しています。
理想はPixel 3aの方の動作です。

原因

  • AQUOSではonPause()でApps with higher priority need memory(メモリ不足)と判断され、バックグラウンドから起動した際に本来通るはずのonResume()ではなく、onCreate()を通ることになったこと
    • 端末によるメモリの違い
    • メモリ不足により、ライフサイクルが変わっていた

原因1. 端末によるメモリの違いとは

AQUOS Pixel 3a
内蔵メモリRAM(作業領域) 3G 4G

比較してみると、Pixel 3aの方がメモリ領域が高いことがわかります。
カービィアプリではジャイロセンサーを使用しており、バックグラウンドに戻った時にメモリが使用されAQUOSではメモリ不足という判断になったと思われます。

原因2. ライフサイクルとは

アプリが起動してから終了するまでの状態のことです。(例:アプリを起動、画面回転、画面遷移したときなど)

Androidのライフサイクル

これがAndroidのActivityのライフサイクルです。
image-20190806020509440.png

各メソッドが呼ばれるタイミングは以下のような感じです。
Activityとは、ユーザーが実際に目にするアプリケーション画面のことです。

メソッド タイミング
onCreate() Activityが初めて生成されたとき(Activityの初期化処理)
onStart() Activityが開始されたとき(画面はまだ表示されない)
onResume() Activityが表示されたとき(画面が表示される)
onPause() Activityがバックグラウンドに移動したとき(別画面に移動)
onStop() Activityが見えなくなったとき(画面は見えない)
onDestroy() Activityが終了するとき(画面が破棄される)

原因1.で記述したように、AQUOSではメモリ不足だと判断されました。

そのため本来のonCreate()→onResume()→onPause()→onResume()の通りにライフサイクルが実行されませんでした。
実際実行されたのは、onCreate()→onResume()→onPause()→onCreate()というライフサイクルでした。
またonCreate()にカービィを動かすメソッドを設置していたため、再度そのメソッドが呼ばれ初期化されていました。

Androidのメモリが足りなくなるとメモリを確保するためにActivityが終了し、再びActivityを表示させようとした場合、改めてonCreate()が呼び出されるようです。

解決方法

onCreate()に設置していた、カービィを動かすメソッドをonResume()に設置しました。
こうすることで、onResume()は必ず通るのでメモリ不足に関係なくカービィを動かすメソッドが実行されるようになり、同じ動作をするようになりました。

所感

今まで曖昧にしていたライフサイクルについて初めてちゃんと向き合う機会になりました。
(正直onCreate()に書けばなんとかなると思っていました。。)

はじめは業務用端末のAQUOSのみで実機確認をしており、先輩社員にコードを見てもらったところライフサイクルと挙動で違和感があるとなり原因を調べました。
調べると「AQUOSだからなんじゃないか」となり、Pixel 3aで試してみたところ思っていた通りの動作(バックグラウンドから起動しても途中から起動する)になり、ここで初めて機種依存だったということに気が付きました。

今回実行する機種によって動作が変わることをレイアウト以外で初めて経験したような気がします。
AndroidにはActivityとFragmentという画面構成の概念があり、それぞれでライフサイクルも違いFragmentの方がより複雑なライフサイクルになっています。
またFragmentのライフサイクルについてもちゃんと理解したいと思います。

ネイティブアプリの場合、ライフサイクルを意識しないとアプリを作ることができないほど重要なものなので今回学ぶことができ非常に良い勉強になりました。

この記事を書いた人

村瀬ゆり
村瀬ゆり
新卒2年目のエンジニアです。
日々Androidの勉強に励んでいます。
趣味は楽器演奏です。