マナティ

Windows 10 アプリ開発入門 ― Universal Windows Platformではじめよう

データを保存、復元しよう―UWP第3回

前回までの連載でUWPアプリの基本的な作りを学びました。今回はアプリを終了すると破棄されてしまっていたデータについて、適切なタイミングで読み込んで復元する"データの永続化"について学びます。

54192_ext_02_0.jpg

データを保存、復元しよう

前回までの記事でUniversal Windows Platform(以下UWP)の基本的な画面の作り方を学ぶことによって、自由な見た目のアプリを作ることができるようになりました。 今回は見た目ではなく、ユーザーから見えないところで動く処理にフォーカスを当てて行きます。その一例として、データの永続化があります。前回までのアプリはアプリ内で取得、処理したデータはアプリが起動している時は保持されますが、アプリを終了するとそのデータはすべて破棄されてしまいます。そのため、アプリは何かしらのタイミングで保持したいデータをファイルに書き出し、適切なタイミングでファイルからデータを読み込んでデータを復元する必要があります。このようなデータを保存、復元することでアプリをいつ起動してもユーザーが作業の続きをすることができる状態にすることをデータの永続化と呼びます。 今回はUWPはどのタイミングでデータを保存、復元すべきなのか、どのようにしてデータを保存、復元するのかの2点について解説していきます。

1. アプリの状態遷移を理解しよう

UWPのアプリは見えないところで状態を保持しており、ユーザーに気付かれないタイミングで状態遷移を行っています。 状態と状態遷移とは何かについては、自動車を例に考えると理解しやすいです。 私たちが普段使用している自動車は走ったり停止したりなど、さまざまな様子に変化します。さらに信号が変わる、運転者が発進するなど、さまざまな要因によって様子が変化します。 そのような車の持っている「様子」を「状態」と呼び、その様子が変化することを「状態遷移」と呼びます。

car.png

自動車の状態と状態遷移

UWPのアプリも同様に常にある状態を保持しており、状態遷移を行うことで様々な変化を示します。 UWPの状態と状態遷移を下図に示します。

state.png

UWPの状態と状態遷移

UWPのアプリが保持している状態は以下の3つとなります。

 ・ NotRunning (終了状態)
 ・ Running (実行状態)
 ・ Suspending (一時停止状態)

NotRunningとRunningは単純にアプリが実行されているか実行されていないかです。Suspendingについては直接目で見ることができないため、皆さんになじみがないとは思いますが、UWPのアプリは一時停止しているときがあります。 一時停止がどういう状態かというと、アプリの処理は実行されないが、メモリ内にはアプリが保持されている状態を示します。

そしてUWPのアプリは上記の3つの状態を、さまざまな要因で遷移します。例えばOSを起動したとき、アプリは実行されていないのでアプリはNotRunning状態にいます。そしてユーザーによってアプリのアイコンがタップされるとアプリが起動し、Running状態へと移ります。 ここでユーザーが別のアプリをしばらく使用し続け、OSによって使用されていないと判断された場合、アプリは一時停止状態へと遷移します。 そのまましばらくアプリが使用されず、OSがシステムリソースの不足を判断したとき、OSによってアプリはNotRunning状態へと遷移させられます。 一方、一時停止状態にあるアプリを再びユーザーが使用を再開すると、アプリはSuspendingからRunningへと状態遷移を行います。 このように、必要なアプリだけ処理を実行させ、システムリソースが不足すると必要に応じて不要なアプリを停止させるという仕組みをとることでWindows10は省電力なシステムを実現しています。

2. データを保存、復元するタイミングを理解しよう

ではアプリはどのタイミングでデータを保存、復元すればデータを紛失することなくアプリのデータを永続化できるでしょうか。 もちろん上図だけでもさまざまなタイミングが存在しますがUWPではRunning(実行状態)とSuspending(一時停止状態)のどちらかに遷移するタイミングでデータを保存、復元する処理を実行することができます。 以下にUWPでのデータ保存、復元をするタイミングとそのイベントを示します。

event.png

UWPでデータを保存、復元するタイミングとイベント

UWPではアプリが一時停止状態になるときにSuspendingイベント、アプリが一時停止から実行状態になるときと終了状態から実行状態に移るときにResumingイベントが発生します。

イベントとは前回までのButtonのClickイベントにあったように、何かしらのアクションが起こったときに任意のプログラム処理を実行できる仕組みのことです。

上図を見ると、アプリが一時停止するとき(Suspendingイベント)にデータを保存、アプリが実行状態に移るとき(Resumingイベント)にデータを復元すれば確実にデータを保存、復元できそうです。

上図の実行状態から終了状態へ遷移するときに何もイベントが発生していないのでデータが保存できないのではないかと思われるかもしれません。アプリが実行状態から終了状態に直接遷移するパターンとしては、ユーザーがタスクマネージャーなどを使ってアプリを強制終了した場合とアプリ内部で例外が発生し、アプリが強制終了した場合です。UWPではそのような場合はデータを保存しないというポリシーなので実行状態→終了状態ではデータ保存の必要性がありません。

つまり、UWPではSuspendingイベントでデータ保存、Resumingイベントでデータの復元を行えばいいことになります。

3. SuspendingイベントとResumingイベントを取得しよう

ではUWPのデータ保存、復元のタイミングを理解できたので実際にデータを保存するプログラムを書いていきます。

今回のデータ保存、復元のプログラムは前回までに作成したアプリのMainPage.xaml.csファイル内に記述していくこととします。

MainPage.xaml.csファイルのMainPageクラスに下記の1.~4.までのコードを記述しましょう。

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();

        //1. Suspendingイベントにイベントハンドラを結びつける
        App.Current.Suspending += OnSuspending;
        //2. Resumingイベントにイベントハンドラを結びつける
        App.Current.Resuming += OnResuming;
    }

    //3. Resumingイベントのイベントハンドラ
    private void OnResuming(object sender, object e)
    {
        //ここにデータ復元の処理を書く
    }
    
    //4. Suspendingイベントのイベントハンドラ
    private void OnSuspending(object sender, Windows.ApplicationModel.SuspendingEventArgs e)
    {
        //ここにデータ保存の処理を書く
    }
}

SuspendingイベントとResumingイベントを取得するにはそれぞれ

App.Current.Suspending += OnSuspending;
App.Current.Resuming += OnResuming;

と記述します。+=はイベントが発生したときに実行させる関数(イベントハンドラ)の名前を記述します。 つまり今回の場合、Suspendingイベントが発生したときOnSuspending関数が、Resumingイベントが発生したときOnResuming関数が呼び出されることになります。

4. データを保存、復元する処理を書こう

では続いてOnSuspending関数とOnResuming関数にデータを保存、復元する処理を記述していきます。

UWPでデータを保存する方法として、最も簡単なものはLocalSettingsというApplicationDataContainerを使う方法です。

ApplicationDataContainerとはKeyとValueでデータを保存することができる仕組みです。KeyとValueを指定してデータを入れると、復元時はKeyを指定するだけでValueを取り出すことができます。

まず必要な名前空間をusingしましょう。

using Windows.Storage;

続いてOnSuspending関数を以下のように編集します。

//4.Suspendingイベントのイベントハンドラ
private void OnSuspending(object sender, Windows.ApplicationModel.SuspendingEventArgs e)
{
    //ここにデータ保存の処理を書く

    //LocalSettingsを取得
    ApplicationDataContainer container = ApplicationData.Current.LocalSettings;
    //data1というキーでhogeという文字列を保存
    container.Values["data1"] = "hoge";

}

LocalSettingsというApplicationDataContainerは以下のコードで取得できます。

//LocalSettingsを取得
ApplicationDataContainer container = ApplicationData.Current.LocalSettings;

コンテナーを取得できたら、Valuesメンバーにキーを指定して値を入れます。 []内に指定した値がキーで、代入する値が保存したいデータとなります。

//data1というキーでhogeという文字列を保存
container.Values["data1"] = "hoge";

これでデータを保存する処理を記述することができました。 続いてデータを復元する処理を書いていきましょう。

OnResuming関数を以下のように編集します。

//3.Resumingイベントのイベントハンドラ
private void OnResuming(object sender, object e)
{
    //ここにデータ復元の処理を書く

    //LocalSettingsを取得
    ApplicationDataContainer container = ApplicationData.Current.LocalSettings;
    //もしdata1というキーがあるなら
    if (container.Values.ContainsKey("data1"))
    {
        //データを復元
        String data = container.Values["data1"].ToString();
        //データを表示
        System.Diagnostics.Debug.WriteLine("保存したデータは "+data);
    }
}

データ復元時は、データがまだ保存されていない可能性もあるため、以下のコードでキーが存在するかを判定します。 もしキーがなければデータがまだ保存されていないことになるので、データを復元する必要はありません。 もしキーが存在するならデータが保存されているのでif文の中でデータを復元すればよいことになります。

//もしdata1というキーがあるなら
if (container.Values.ContainsKey("data1"))
{
}

ApplicationDataContainerからデータを復元するには保存時と同様に Valuesに保存したキーを指定してデータを取り出します。

//データを復元
String data = container.Values["data1"].ToString();

今回は動作確認をするため、Debugクラスを利用して以下のコードでVisual Studioの出力ウインドウに保存したデータを出力してみます。

//データを表示
System.Diagnostics.Debug.WriteLine("保存したデータは "+data);

5. SuspendingとResumingをデバッグしよう

UWPのアプリはバックグラウンドに回ると一時停止状態に入り、Suspendingイベントが発生しますが、バックグラウンドに回ってすぐに発生するわけではなく、発生するタイミングはOSによって決定されます。 そこでVisual StudioではUWPアプリを中断状態、再開状態にするデバッグ用の機能があります。 今回はその機能を使って中断と再開をデバッグしてみましょう。

まずは通常と同じように[ローカルコンピュータ]をクリックもしくは[F5]キーでデバッグを開始しましょう。

debug.png

デバッグ開始ボタン

デバッグを開始すると[ライフサイクルイベント]というボタンが現れます。

lifecycle.png

ライフサイクルイベントボタン

ライフサイクルイベントボタンの横にある三角形を押します。 すると[中断]、[再開]、[中断とシャットダウン]というボタンが現れます。 この中のどれかを押すと、アプリはその状態へと状態遷移を行います。

では[中断]ボタンを押してみましょう

suspending.png

中断ボタン

特にアプリに変化は訪れませんが、これでSuspendingイベントが発火し、OnSuspending関数内の処理が実行されています。

では同様に。再開ボタンを押してアプリを一時停止状態から実行状態へと移しましょう。

resuming.png

再開ボタン

今回の場合、データが正しく保存、復元できているならVisual Studioの出力ウインドウに保存したデータが表示されるはずです。 出力ウインドウを見てみると、確かにデータが保存、復元できていることを確認することができました。 今回はVisual Studioのボタンを押すことで強制的に一時停止させたり、再開させたりしましたが実際にアプリが動くときはOSによって判断されたタイミングで一時停止や再開が実行されるので気を付けましょう。

out.png

Visual Studioの出力ウインドウに保存したデータが表示される様子

6. まとめ

今回はUWPのデータの保存と復元の方法を解説しました。データの永続化は非常に重要で、例えばテキストファイルを編集するアプリを作った場合別のアプリを使っていたらデータが消えていた、アプリを閉じてもう一度起動すると編集していたデータが消えたという状況になりかねません。ですので適切なタイミングでデータを保存、復元し、ユーザーがきちんと作業のできるようにアプリの実装に気を遣う必要があります。 皆さんもデータを永続化させ、長く使ってもらえるアプリを目指して作ってみましょう。

著者プロフィール

栂井良太(著者)
Microsoft MVP for Windows Development、Microsoft Student Partners
Windowsのデスクトップソフトを趣味で作成しているうちにWindowsに関連した技術に関心を持ち、Windows Phone 7、Windows 8などのアプリに関連した情報をブログ、オフラインコミュニティにて発信、現在はUniversal Windows App、Azureなどを普及すべく情報発信中。
Webサイト:http://garicchi.com