Windowsストア・アプリには、「終了した後で再実行されるときに、ページの状態を復元しろ」というルールがある。とても面倒そうだが、どうすればよいのだろうか。
powered by Insider.NET
前回のTIPSでは、Windowsストア・アプリ(旧称: Metroスタイル・アプリ)で表示したページの状態を維持するために、ページのインスタンスを保持しておく方法を説明した。しかしさらに、「終了した後で再び実行されるときも、ページの状態を復元しろ」というルールがある。とても面倒そうだが、どうすればよいのだろうか?
そこで本稿では、アプリの起動時に以前のページの状態を復元する方法を説明する。
●事前準備
Windows 8(以降、Win 8)向けのWindowsストア・アプリを開発するには、Win 8とVisual Studio 2012(以降、VS 2012)が必要である。これらを準備するには、第1回のTIPSを参考にしてほしい。本稿ではWin 8とVS 2012 Expressを使用している。
●リジュームの課題
Windowsストア・アプリのライフサイクルは、次の図のように説明される。
詳細は特集記事「Metroスタイル・アプリの開発者が知るべき3つのこと」を参照してほしいが、一度終了した後で次に起動(=アクティブ化)されるときは、ユーザーには中断状態からの再開(=リジューム)と同じに見せかけなければならない。
リジューム時には、次に示すような事項を復元する必要があるだろう。
●表示していたページとナビゲーション履歴をリジュームするには?
幸いなことに、[グリッド アプリケーション(XAML)」や[分割アプリケーション(XAML)]などのプロジェクト・テンプレートにより(ひな型コードとして)自動生成されたSuspensionManagerクラスが、表示していたページとそこまでのナビゲーション履歴の保存と復元をサポートしている。
また、正常に終了されなかった場合は、リジュームせずに初期状態でアクティブ化しなければならないのだが、その切り分けも自動生成されたAppクラスがサポートしている。
●表示データをリジュームするには?
画面に表示していたデータは、少なければローカルに保存しておいてもよいが、多い場合はリジューム時に再取得した方がよいだろう。その場合は、再取得するために必要なパラメータだけを保存しておく。データを保存・復元する方法は次項の入力データと同様である。
●入力データを保存するには?
入力中の文字列を保存・復元するコードを実装してみよう。新しく[グリッド アプリケーション (XAML)]プロジェクトを作り、適当にテキストボックスを配置する(名前は「userInputTextbox」とする)。
そのページのSaveStateメソッドに次のコードを記述する。なお、このメソッドは、自動生成されたLayoutAwarePageクラスのメソッドをオーバーライドしている。そのページにSaveStateメソッドが存在しないときは、「override」と打ってIntelliSenseを出し、その一覧から「SaveState」メソッドを選択すれば、メソッドのスケルトンが自動生成される。
protected override void SaveState(Dictionary<string, object> pageState)
{
base.SaveState(pageState);
pageState["userInputText"] = userInputTextbox.Text;
}
Protected Overrides Sub SaveState(pageState As Dictionary(Of String, Object))
MyBase.SaveState(pageState)
pageState("userInputText") = userInputTextbox.Text
End Sub
テキストボックスの文字列を保存するコード(上:C#、下:VB)
[グリッド アプリケーション (XAML)]プロジェクト・テンプレートで自動生成されたGroupedItemsPage.xaml.cs/.vbファイルにメソッドを追加した例。
なお、データは「_sessionState.xml」(=SuspensionManagerクラスのsessionStateFilename定数として定義されている)という名前のファイルに保存される。保存されるフォルダは、Win 8がインストールされているドライブの「\Users\{ユーザー名}\AppData\Local\Packages\{パッケージ・ファミリ名}\LocalState」になる。ここで、{パッケージ・ファミリ名}は、アプリケーション・マニフェスト・ファイル(=[ソリューション エクスプローラー]上から[Package.appxmanifest]ファイル項目を開き、[パッケージ化]タブの[パッケージ ファミリ名]欄)に記述されている一意の識別名である(この値を変更するには、[パッケージ化]タブの[パッケージ名]欄を設定し直せばよい)。
●中断時の処理をテストするには?
さっそく先ほどのコードを試してみよう。デバッグ時には、以下のようにしてVS 2012で中断をシミュレートする。
まず、そのための[デバッグの場所]ツールバーを表示させる。メニューバーから表示させるには、[表示]−[ツール バー]−[デバッグの場所]を実行する。あるいは、次の画像の説明のようにしてもよい。
[デバッグの場所]ツールバーには、次の画像のように[中断]というコマンドがあり、デバッグ中に中断や再開などをシミュレートできる。
それでは実際にデバッグ実行して、次の画像のようにテキストボックスに何か入力したところで、中断してみてほしい。
これで前述の_sessionState.xmlファイルが作成されたはずだ。メモ帳などで内容を確認できる。
なお、SaveStateメソッドはページが移動するときにも呼び出される(実際に保存されるのは中断時)。
●入力データを復元するには?
先ほどのコードで保存した文字列を復元するには、そのページのLoadStateメソッドに次のようにコードを追加する。
protected override void LoadState(Object navigationParameter,
Dictionary<String, Object> pageState)
{
var sampleDataGroups
= SampleDataSource.GetGroups((String)navigationParameter);
this.DefaultViewModel["Groups"] = sampleDataGroups;
// ↓テキストボックスに入力されていた文字列を復元する
if (pageState != null)
userInputTextbox.Text = pageState["userInputText"].ToString();
}
Protected Overrides Sub LoadState(navigationParameter As Object, _
pageState As Dictionary(Of String, Object))
Dim sampleDataGroups As IEnumerable(Of Data.SampleDataGroup) _
= Data.SampleDataSource.GetGroups(DirectCast(navigationParameter, String))
Me.DefaultViewModel("Groups") = sampleDataGroups
' ↓テキストボックスに入力されていた文字列を復元する
If pageState IsNot Nothing Then
userInputTextbox.Text = pageState("userInputText").ToString()
End If
End Sub
テキストボックスの文字列を復元するコード(上:C#、下:VB)
[グリッド アプリケーション (XAML)]プロジェクト・テンプレートで自動生成されたGroupedItemsPage.xaml.cs/.vbファイルに記述した例。
これで、入力中に中断してから終了させ、その後に再び実行すると、文字列が復元されて表示されるはずである。
なお、LoadStateメソッドはページのインスタンスが作られたときに呼び出される。そのため、入力中にほかのページへ移動してから再び戻って来たときにも文字列が復元される。前回のTIPSではページのインスタンスを保持したが、このようにしてもページの状態を復元できるのである。
●まとめ
起動時に以前の画面を復元するには、ページごとにSaveStateメソッドとLoadStateメソッドでデータの保存・復元処理を行えばよい。
アプリのライフサイクルの設計や実装については、次のURLが参考になる。
なお、本稿では説明しなかったが、「強制終了されても失ってはいけないアプリ・データの場合には、ApplicationDataクラス(Windows.Storage名前空間)のRoamingSettingsプロパティかLocalSettingsプロパティに保存する」ということも覚えておいてほしい。
Copyright© Digital Advantage Corp. All Rights Reserved.