Edited at

ストアアプリのターミネーターに対処せよ!(事件編)

More than 5 years have passed since last update.

Windows ストアアプリにはおそろしい「ターミネーター」がひそんでいるのをご存じでしょうか。

今回、次回と2部構成にてストアアプリが対処しなければならないこの「ターミネーター」について

ご紹介したいと思います。

たとえばグリッドアプリケーションのテンプレートで構築された、Web API から取得した写真画像のビューアアプリを想像してみてください。

上記のように詳細画面で1枚の写真画像を表示したのち、アプリを他のものに切り替えて

いろいろと作業をしたあとに元のアプリに戻ってみると・・・

消ーえーてーるー!・・・こんな現象を目撃されたことはないでしょうか。

これこそがストアアプリのターミネーターの仕業なんです。


Windows ストアアプリのライフサイクル

ターミネーターの正体とは何なのか、それを解くカギは Windows ストアアプリの

ライフサイクルにあります。

Runing(実行中)、NotRunning(停止)、Suspended(中断)の3つの実行状態の

遷移を表した上記の図を見たことのある方も多いと思います。

実行中にストアアプリが切り替わり非アクティブになると中断され、再びアクティブになると

再開して実行中の状態に戻ることが読み取れます。もしそれだけだとしたら、

先ほどの例のような現象は起こらず再び元の写真画像が表示されるはずですが・・・。

実はストアアプリの実行状態は正確にはもっと細かく分類されています。


ApplicationExecutionState.cs

namespace Windows.ApplicationModel.Activation

{
// 概要:
// アプリケーションの実行状態を指定します。
[Version(100794368)]
public enum ApplicationExecutionState
{
// 概要:
// アプリケーションが実行されていません。
NotRunning = 0,
//
// 概要:
// アプリケーションが実行されています。
Running = 1,
//
// 概要:
// アプリケーションが中断しています。
Suspended = 2,
//
// 概要:
// アプリケーションは中断後に終了されました。
Terminated = 3,
//
// 概要:
// アプリケーションはユーザーによって閉じられました。
ClosedByUser = 4,
}
}

ライフサイクルの図にはない「Terminated」と「ClosedByUser」という状態がありますね。

これをあらためて図に起こしてみるとおおよそ下記のような感じになります。

ClosedByUser はユーザーにより終了されたかどうか以外、状態の遷移としては NotRunning と

それほど変わらないです。

しかし、Terminated はメモリ容量が少なくなった場合に OS により終了され、再度アプリが

起動する場合には元の状態に戻す復帰処理をともなうという特殊な遷移をします。

ユーザーが知らないところで OS が終了させたわけですから、再度アプリをアクティブ化して

再開させた場合に元の状態に戻ることは当然ユーザーから期待される動作ですね。

下記の情報でも、Terminated から起動した場合のみ、セッションデータを復元することが

推奨されています。

アプリケーションのライフサイクル (Windows ストア アプリ) ー 終了した理由

終了した理由
PreviousExecutionState
実行する処理

システムによる終了
Terminated
セッション データを復元する

ユーザーによる終了
ClosedByUser
既定のデータで起動する

予期しない終了
NotRunning
既定のデータで起動する

終了した場合はメモリ上からアプリのデータはいったんすべて消えてしまいますが、

Terminated で終了した場合、再度起動された際には元のデータを復元しなければなりません。

冒頭にあった復帰時に写真が表示されない現象は、このセッションデータの復元が不完全なために

起こった問題だったわけです。


次回予告

もうおわかりでしょう・・・ターミネーターの正体は OS である Windows です。

システムのリソースが十分になくアプリをメモリに保持できない場合は、中断中のアプリから

終了させて OS の稼働を維持する働きをしているわけですね。

この強制的な終了からはストアアプリは逃れられません・・・ならば完全なアプリデータの

復元をするしかない!ということで次回はこの復帰処理の具体的な実装例をご紹介したいと思います!