Windows 8 のアプリ ライフサイクル モデルでは、ユーザーがどのアプリを実行するか管理する必要がなくなります。また開発者は、アプリがバックグラウンドに存在する場合に、デバイスのバッテリまたはパフォーマンスに影響しない優れたユーザー エクスペリエンスを簡単に作成できます。新しいライフサイクル イベントを使用することにより、画面に表示されておらず、実行したことがないアプリでも、常に動作しているように感じられます。

最近では、すべてのユーザーが未使用のアプリであっても実行したままにすることが多いので、ラップトップ、タブレット、および携帯電話でバッテリが不足気味になります。これが行われるのは、利便性とアプリ間の切り替えの迅速化のためです。

私たちはこうしたことを考慮して、アプリの応答性とバッテリ寿命を維持し、一貫性のある優れたパフォーマンスを提供するために、Windows 8 の Metro スタイル アプリ向けにライフサイクル モデルを開発しました。Metro スタイル アプリはすべて、全画面表示のイマーシブ エクスペリエンスに関係しています。そのために、Windows 8 の新しいライフサイクル モデルでは、フォアグラウンドのアプリに焦点を当てることでユーザーが没入するエクスペリエンスを維持しながら、デバイスの全能力を引き出します。この記事では、ライフサイクル モデルの新しい状態を紹介すると共に、優れたアプリを作成するために必要なことを説明します。

Metro スタイルのアプリのライフサイクル

Metro スタイル アプリは、任意の時点で 4 つのライフサイクル状態 (非実行状態実行状態中断状態、または終了状態) のいずれかです。アプリが状態を遷移すると、ユーザーに対して一貫性のある高パフォーマンスのエクスペリエンスを提供するのに役立つライフサイクル イベントを受け取ります。

次の図は、Metro スタイル アプリが状態間をどのように遷移するかを示しています。

3 つのボックスと、それを結ぶ環状パターンを示す矢印。非実行状態 > アクティベーション > 実行状態 > 中断中 > 中断状態 > 終了中 > 非実行状態

すべての Metro スタイル アプリは、ユーザーがアプリを起動し、アプリ間を切り替え、アプリを閉じると、それに伴ってこれらの状態を移行します。ユーザーがアプリ間の切り替えを行うと、それに合わせてアプリは実行状態中断状態の間を頻繁に移行することになります。したがって、アプリではライフサイクル イベントを処理する必要があります。

アプリがライフサイクルの状態間で遷移するときに、ライフサイクル イベントを受け取ります。

イベント 遷移元 遷移先

アクティベーション

非実行状態

実行状態

中断中またはチェックポイント (WinJS)

実行状態

中断状態

再開中

中断状態

実行状態

中断

一般に、Metro スタイル アプリは、ユーザーが別のアプリに切り替えると実行を停止します。Windows は、フォアグラウンドにないアプリを中断します。アプリが中断されると、メモリ内に凍結されます。この状態では実行できませんが、Windows はユーザーがアプリに戻ったときに直ちに再開できます。この方法により Windows は、フォアグラウンド アプリでシステム リソースをより有効に活用しながら、バックグラウンドのアプリでユーザーのバッテリが消耗しないようにできます。

アプリがフォアグラウンドから移動した場合、Windows は元のアプリへの迅速な切り替えを可能にするために数秒間待機した後、アプリの中断を試みます。アプリは、中断中またはチェックポイントの (JavaScript) イベントに登録しておく必要があります。このイベントは、Windows がその中断を望む場合に受け取ることになります。これは、アプリにとって重要なタイミングです。この機会を使用して、維持する必要があるアプリ データを永続的な記憶域に保存します。通常、アプリはそのまま再開されます。永続化されたデータはメモリ内に依然として存在するので、取得する必要はありません。ただし、Windows がシステム リソースを解放するためにアプリを終了する場合に備えて、このデータは保存しておく必要があります。アプリを中断した場所からユーザーが再開するための十分なアプリ データを保存してください。この方法により、皆さんの顧客はアプリが常に動作しているものと感じます。

アプリが中断イベントを受信してから 5 秒以内にその中断イベント ハンドラーから戻らなければ、Windows はアプリを終了します。中断イベント ハンドラーでは、過度の処理を行わないことが重要です。アプリ データを保存し、迅速に復帰します。

この記事では、例として株式アプリを使用します。このアプリは、中断イベントを使用して、ユーザーが表示した最後の株価と、株式チャートの時間範囲を保存します。そして、アプリを終了した場合、前回にユーザーがアプリを表示していたまったく同じ画面で再起動できます。たとえば、株式アプリでは、Windows により中断する前にアプリのタイルを最新情報で更新するために、ローカル タイル通知を送信するもう 1 つの機会としてこのタイミングを使用することをお勧めします。

JavaScript での中断の処理

JavaScript 用 Windows ライブラリ (WinJS) を使用して Metro スタイル アプリを記述する場合、中断を処理するためにチェックポイント イベントを使用できます。

var app = WinJS.Application;

function checkpointHandler() {
// The checkpoint event gives us the chance to save application data.
// In this case, we save the current stock info that the user is viewing.
app.sessionState.lastSeenStock = selectedStock;
app.sessionState.lastSeenRange = selectedRange;

// Send client side notifications
Tile.sendTileUpdate(selectedStock, stockInfo.change, stockInfo.lastSale,
stockInfo.lastSaleTime, stockInfo.open);
}

app.addEventListener("checkpoint", checkpointHandler);

これは概要に過ぎません。詳細については、デベロッパー センターのアプリを中断する方法 (JavaScript および HTML) (英語) を参照してください。

XAML での中断の処理

XAML および C# を使用して Metro スタイル アプリを記述した場合、アプリの中断を処理するためにアプリケーション オブジェクトで Suspending イベントを使用できます。

public App()
{
InitializeComponent();
this.Suspending += new SuspendingEventHandler(OnSuspending);
}

async protected void OnSuspending(object sender, SuspendingEventArgs args)
{
// The Suspending event gives us the chance to save application state
// In this case, we save the current stock info that the user is viewing

// Because writing to a file is asynchronous, we grab a deferral which ensures
// that suspending doesn’t complete until our file write is complete
SuspendingDeferral deferral = args.SuspendingOperation.GetDeferral();

// Here we create a SuspensionManager class which handles adding session data
// to a Dictionary and then serializing that data to a file
SuspensionManager.SessionState["lastSeenStock"] = stock;
SuspensionManager.SessionState["lastSeenRange"] = range;
await SuspensionManager.SaveAsync();

// Send client side notifications
Tile.SendTileUpdate(stock, stockInfo.Change, stockInfo.LastSale,
stockInfo.LastSaleTime, stockInfo.Open);

deferral.Complete();
}

ここでも、これは概要であることに注意してください。XAML および C# で中断を処理する方法に関する詳細については、デベロッパー センターのアプリを中断する方法 (VB/C#/C++ および XAML) (英語) を参照してください。

再開

アプリを再開すると、Windows により中断された時点の状態から続行します。具体的には、アプリの中断中に、アプリのデータおよび状態はメモリ内で維持されます。したがって、アプリの再開時には、すべてがアプリの中断時のままです。再開イベントの受信時には、保存されたデータを明示的に復元する必要はありません。

ただし、アプリが常に動作しているように感じられることが大切です。このためには、接続し、最新のデータを表示する必要があります。再開前に非常に長い期間、中断状態でアプリがとどまることがあります。データまたはネットワーク接続が古くなり、アプリの再開時に更新することが必要になる場合があります。ユーザーがフォアグラウンドにアプリを移行すると、アプリは再開イベントを受信します。アプリがこのイベントを受信すると、アプリのコンテンツを更新し、ネットワーク リソースに再接続できます。

この例では、株式アプリの再開は、中断前にアプリが保持していたキャッシュ済み株式データをすべて更新するために適した場所です。以前のデータが数時間、さらには数日間も経過している場合があります。ユーザーがこの古いデータを見ると、アプリが常に動作しているという感覚が失われてしまいます。再開時には、株式アプリがすべてのデータを更新する必要があります。これによって、アプリがフォアグラウンドに移動するたびに、ユーザーに最新の株価、チャート、およびニュース記事が提示されます。

JavaScript での再開の処理

JavaScript では、Windows.UI.WebUI.WebUIApplication 名前空間で Windows ランタイムの再開イベントを使用できます。これは、JavaScript アプリ専用に意図された再開イベントです。

function resumingHandler() {
//Update the selected stock with the latest news, stock info, and chart data
News.requestNews(stock);
Api.getStockInfoData(stock).then(function(data){displayStockInfo(data); });
Api.getHistoryData(range).then(function (chartData)
{CanvasChart.drawChart("chartCanvas", chartData, Chart.getChartOptions(false));});

// Send client side notifications
Tile.sendTileUpdate(stock, stockInfo.change, stockInfo.lastSale,
stockInfo.lastSaleTime, stockInfo.open);
}

Windows.UI.WebUI.WebUIApplication.addEventListener("resuming", resumingHandler);

詳細については、デベロッパー センターのアプリを再開する方法 (JavaScript および HTML) (英語) を参照してください。

XAML での再開の処理

XAML および C# を使用して Metro スタイル アプリを記述した場合、アプリの再開を処理するためにアプリケーション オブジェクトで Resuming イベントを使用できます。

public App()
{
InitializeComponent();
this.Resuming += new EventHandler<object>(App_Resuming);
}

async private void App_Resuming(object sender, object e)
{
//Update the selected stock with the latest news, stock info, and chart data
News.RequestNews(stock);

Data data = await Api.GetStockInfoDataAsync(stock);
Api.DisplayStockInfo(data);

Chart chartData = await Api.GetHistoryDataAsync(range);
CanvasChart.DrawChart("chartCanvas", chartData, Chart.GetChartOptions(false));

// Send client side notifications
Tile.SendTileUpdate(stock, stockInfo.Change, stockInfo.LastSale, stockInfo.LastSaleTime, stockInfo.Open);
}

VB/C#/C++ および XAML で再開を処理する方法に関する詳細については、デベロッパー センターのアプリを再開する方法 (VB/C#/C++ および XAML) (英語) を参照してください。

アクティベーション

アクティベーションはすべて、アプリの起動方法に関係します。これは、Metro スタイル アプリで多くの目的のために動作します。コントラクトを処理するための Metro スタイル アプリ アクティベーションの使用方法に関する詳細については、以前の記事アプリでの Windows 8 コントラクトのアクティベーション (英語) を参照してください。ここでは、Windows によりアプリが終了され、ユーザーがアプリを再度起動した場合に、以前に保存されたデータを復元するためにアクティベーションを使用する方法について焦点を当てます。

Windows は、さまざまな理由で中断されたアプリを終了できます。たとえば、ユーザーが手動でアプリを閉じたときや、サインアウトしたとき、またはシステムのリソースが不足したときに、アプリが終了されます (ゲームなど一部のアプリでは、リソース使用量が非常に多くなることがあります)。Windows によりアプリが終了された後、ユーザーがアプリを起動すると、アプリはアクティベーション イベントを受信し、アプリがアクティベーションされるまでユーザーにはアプリのスプラッシュ スクリーンが表示されます。アプリが最後に中断されたときに保存されたデータを復元する必要があるかどうか、またはアプリの既定のデータを読み込む必要があるかどうかを特定するために、このイベントを使用できます。アクティベーション イベントの引数には、アクティベーションされる前のアプリの状態を伝える PreviousExecutionState プロパティが含まれます。このプロパティは、Windows.ApplicationModel.Activation.ApplicationExecutionState 列挙値の 1 つです。

終了の理由 PreviousExecutionState 値 実施すべき措置
システムによる終了 (リソースの制約、シャットダウン、再起動などに起因)。

Terminated

セッション データの復元

ユーザーによって閉じられた

ClosedByUser

既定のデータで開始

          予期せずに終了したか、またはユーザー セッションの開始以降にアプリが実行していない

NotRunning

既定のデータで開始

PreviousExecutionState は、値 Running または Suspended を持つ可能性もありますが、これらの場合はアプリは以前に終了していませんので、データの復元について考慮する必要はありません。

アプリがアクティベーションされ、その PreviousExecutionStateTerminated であった場合、ユーザーに最後に表示された状態にアプリを戻すために、保存されたセッション データを復元する必要があります。ユーザーがアプリを手動で閉じた場合、アプリが予期せずに終了した場合、または現在のセッションでまだ実行されていない場合は、以前のセッション データを無視し、既定のビューでアプリを開始する必要があります。

この例の株式アプリでは、中断時に保存された株式およびチャートの情報を復帰するためにアクティベーション イベントを使用します。またアプリは、キャッシュされたネットワーク データを更新します。この方法によりユーザーには、アプリを切り替えたときに表示されていた同じ株価が表示されますが、株価、チャート、およびニュース記事はすべて最新の情報です。

JavaScript でのアクティベーションの処理

JavaScript 用 Windows ライブラリ (WinJS) を使用して Metro スタイル アプリを記述する場合、アクティベーションを処理するためにアクティベーション イベントを使用できます。

アプリは、アクティベーション イベント ハンドラーのコードで、sessionState オブジェクトをチェックすることにより、保存されたデータを読み込む必要があるかどうか、または既定のホーム ビューを表示すべきであるかどうかを特定できます。SessionState は、eventArgs.detail.previousExecutionState を調査することにより、アプリの最後の状態を自動的に特定します。sessionState に入力されている場合は、それを使用してセッション データを復元し、入力されていない場合はアプリの既定のデータを使用します。

var app = WinJS.Application;

function activatedHandler(eventArgs) {
if (eventArgs.detail.kind == Windows.ApplicationModel.Activation.ActivationKind.launch) {
// Check whether the session state variables are valid.
// If so, retrieve the stock and range values saved in the checkpoint handler
if (app.sessionState) {
stock = app.sessionState.lastSeenStock;
range = app.sessionState.lastSeenRange;
}
// If not, use the app's default values
else{
stock = "DOW";
range = "1M";
}

// Initialize the WinJS controls asynchronously behind the app splash screen
// Start retrieving the latest stock data asynchronously after the controls are ready
eventObject.setPromise(WinJS.UI.processAll().then(function() {
Api.initializeUserStocks();
}));
}
}

app.addEventListener("activated", activatedHandler);

       

JavaScript でのアクティベーションの処理方法に関する詳細については、デベロッパー センターのアプリをアクティベーションする方法 (JavaScript および HTML) (英語) を参照してください。

XAML でのアクティベーションの処理

XAML および C# を使用する Metro スタイル アプリでは、タイルからの基本的なアクティベーションを処理するために OnLaunched イベントをオーバーライドできます。

アプリは、OnLaunched イベント ハンドラー コードで、イベント引数の PreviousExecutionState をチェックできます。これが Terminated である場合Suspending イベントで保存されたデータを復元します。この値が異なる場合は、アプリの既定のデータを使用します。

async protected override void OnLaunched(LaunchActivatedEventArgs args)
{
// Check whether the session data should be restored
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
// Here we've created a SuspensionManager class which handles restoring session
// data from a file and then gives access to that data through a Dictionary
await SuspensionManager.RestoreAsync();

// Retrieve the stock and range values saved in the suspend handler
stock = SuspensionManager.SessionState["lastSeenStock"];
range = SuspensionManager.SessionState["lastSeenRange"];
}
// If not, use the app's default values
else
{
stock = "DOW";
range = "1M";
}

// Start retrieving the latest stock data
Api.InitializeUserStocks();

Window.Current.Activate();
}

XAML でアクティベーションを処理する方法に関する詳細については、デベロッパー センターのアプリでアクティベーションする方法 (VB/C#/C++ および XAML) (英語) を参照してください。

優れたアプリのライフタイム エクスペリエンスを作成するためのヒント

これですべての基礎知識が得られたので、次にユーザーにとってアプリが常に動作していて最新の情報を提示していると感じられる優れたライフタイム エクスペリエンスを構築するのに役立つヒントをいくつか示します。

時に、一からやり直すことが最善

ユーザーが最後にアプリを表示してから経過している期間が長すぎるときには、アプリを既定のビューにリセットすることが最も良い場合もあります。どの程度の期間が長すぎると考えるかは皆さんしだいですが、アプリのコンテンツが古くなったと考えられる場合には、アプリをホーム ビューにナビゲートすることをお勧めします。これによって、ユーザーにとってアプリがよりインテリジェントに見えます。

たとえば、ニュース リーダー アプリを構築している場合、ユーザーがそのアプリからの切り替えを行った後、アプリはおそらく中断されます。そして後で、ユーザーがニュース リーダー アプリに戻ると、アプリが再開されます。再開ハンドラーで、現在の記事の経過期間をチェックし、それが古くなっているかどうかを特定してください。記事が古すぎる場合は、古い記事の代わりに既定のホーム ビューを表示します。

適切なデータを適切な時期に保存する

常に、アプリのライフ全体にわたって段階的に重要なデータを保存します。アプリが中断イベント ハンドラーのコードを実行するための時間は最大でわずか 5 秒であるために、中断時までに重要なアプリ データが永続的な記憶域に保存されていることを確認する必要があります。

アプリを記述する場合、セッション データおよびユーザー データの 2 種類のデータを管理します。セッション データは、アプリを使用するユーザーの現在のエクスペリエンスに関連する一時データです。たとえば、ユーザーが表示している現在の株価、電子ブックでユーザーが読んでいる現在のページ、長い項目一覧でのスクロール位置などがこのデータです。どのような場合でも、ユーザー データは永続的であり、ユーザーが常にアクセスできることが必要です。たとえば、ユーザーの入力途中のドキュメント、アプリで取得した写真、ユーザーのゲームの進行状態などがこのデータです。

アプリが中断されるまでに、両方のデータの種類を永続的な記憶域に保存するようにしてください。

セッション データの復元

ユーザーは一般に、Metro スタイル アプリが前回の使用時に終了したときのままの状態にあることを期待しています。開発者の観点からは、アプリが中断された状態から再開するか、または非実行状態からアクティベーションする場合、以前に保存されたセッション データを復元することが多くの場合に適切です。

たとえば、アプリにショッピング カート機能が含まれている場合で、ユーザーがカートに品目を追加した後、そのアプリからの切り替えを行ったときは、ユーザーがアプリを再開するか再アクティベーションを行ったときに、カート内の品目を維持することは理にかなっていると思われます。

もう 1 つの例として、ニュース記事を表示するアプリを考えます。ユーザーが特定の記事を表示しており、次に別のアプリに切り替えた場合、ユーザーがアプリに戻ったときには元の記事が表示されることを期待します。

中断イベント ハンドラーで排他的なリソースをリリースする

アプリが実行中に排他的なリソースを取得している場合 (ファイル ハンドルや外部デバイスへの参照など)、中断イベントを受信したときにそうしたリソースをリリースする必要があります。さらにアプリは、再開イベントの受信時に続行する必要がある場合に、こうした排他的リソースを回収する必要があります。

アプリを閉じないでください!

Windows 8 の Metro スタイル アプリでは、アプリ自身を閉じないでください。また、ユーザーがアプリを閉じることを可能にするアプリ UI を提示しないでください。システムのパフォーマンスおよびバッテリ寿命を維持するために、アプリの中断および終了はユーザーに代わって Windows によって処理されます。ユーザーがアプリを閉じるときは、画面の上から下にスワイプするか、または Alt + F4 キーを押します。

終わりに

3 つのイベント保留再開、およびアクティベーションを使用することによって、アプリはユーザーにとって常に動作しているように感じられます。ただしそれと同時に、未使用時にはバッテリの不必要な消耗またはシステムのパフォーマンスの低下を招くことはありません。よりスリムでよりモバイル性の高いデバイス環境では、新しい Metro スタイル アプリのライフサイクルによりどのデバイスでもアプリの魅力が高まるはずです。

--Windows プログラム マネージャー、Adam Barrus

この記事はグループで作成されました。共同執筆者: Jake Sabulsky、Ben Srour、Ben Betz、Marco Matos、Ryan Haveson、Ian LeGrow、および John Montgomery。