かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

PrismのViewModelでイベントの購読解除などの後始末をするタイミング

PrismのViewModelには画面遷移してきたタイミングで呼ばれるOnNavigatedToと画面から離れるときやサスペンド時に呼ばれるOnNavigatingFromメソッドがあります。ページが有効な間はイベントを購読したいというケースでは、OnNavigatedToでイベントの購読を行い、OnNavigatingFromで購読解除すると一見よさそうに見えます。

デバッガをアタッチしてる状態では、それでいいのですが、デバッガをアタッチしてない状態では画面を最小化したり電話でバックグラウンドに回した時に、実はOnNavigatingFromがsuspending引数がtrueになって呼び出されます。サスペンドからの復帰時にはOnNavigatedToは呼ばれないという厄介な状態になります。(完全にアプリが終了されたら起動シーケンスからやり直しなので呼ばれますが)

なので、OnNavigatingFromで無条件に購読解除すると、サスペンドからの復帰時にイベントの処理が動かないという状況になったりします。これを回避するには以下のように、suspendingがfalseの時だけイベントの購読解除をするといったような処理が必要になります。

public override void OnNavigatedTo(NavigatedToEventArgs e, Dictionary<string, object> viewModelState)
{
    base.OnNavigatedTo(e, viewModelState);

    // ここでイベント購読
}

public override void OnNavigatingFrom(NavigatingFromEventArgs e, Dictionary<string, object> viewModelState, bool suspending)
{
    base.OnNavigatingFrom(e, viewModelState, suspending);

    if (!suspending)
    {
        // ここでイベント購読解除
    }
}

ちょっとはまった。