Monday, 17 February 2014

Saving and restoring service class state using Prism for the Windows Runtime

Previously I wrote about how Prism for the Windows Runtime can be used to save and restore view state. This is achieved by overriding the SaveState and LoadState methods in a page that derives from the VisualStateAwarePage class, and then saving the desired state. I extended the sample photo viewer app so that the user will see the page content scrolled to the exact location it was at prior to termination or navigation, regardless of whether the page orientation has changed in between termination and reactivation.

Less well known is that Prism provides support for saving state from other classes, such as service classes. Therefore, in this blog post I’ll explain how state can be saved from a service class so that it survives termination, and how it can be restored upon reactivation.

Implementation

Suspend

In order for a service class to persist state to survive termination it must use an instance of the SessionStateService class, which implements the ISessionStateService interface. Therefore, the OnInitialize method in the App class needs to register the types with a dependency injection container.

protected override void OnInitialize(IActivatedEventArgs args)
{
    ...
    _container.RegisterInstance<ISessionStateService>(SessionStateService);
}

The code above registers the instance of the SessionStateService that’s created in the MvvmAppBase class with the ISessionStateService interface. The container will cache the instance on behalf of the app, with the lifetime of the instance being tied to the lifetime of the container.

The SomeService class has the SessionStateService instance injected as a dependency when the SomeService class is created.

public class SomeService
{
    private readonly ISessionStateService _sessionStateService;
 
    private const string SomeValue1Key = "SomeValue1";
    private const string SomeValue2Key = "SomeValue2";
    private string _someValue1, _someValue2;
 
    public SomeService(ISessionStateService sessionStateService)
    {
        _sessionStateService = sessionStateService;
        ...
    }
     
    ...
}

The constructor simply stores the SessionStateService instance in a private field. Then to save some service class state the SaveState method should be called.

private void SaveState(string someValue1, string someValue2)
{
    _sessionStateService.SessionState[SomeValue1Key] = someValue1;
    _sessionStateService.SessionState[SomeValue2Key] = someValue2;
}

The SaveState method shows how the SomeService class persists two string values so that they’ll survive termination. The required values are stored in the SessionState dictionary of the SessionStateService instance. When the app suspends, or page navigation occurs, these values will be written to the _sessionState.xml file.

Resume

When an app resumes from suspension it continues from where it was when it was suspended, as the app is still stored in memory. Therefore,no special behaviour is associated with resuming from suspension.

Activation

Windows may terminate an app after it’s been suspended, if the system is low on resources. If a service class has persisted state to survive termination, it must be restored when the app reactivates. This can be achieved in the constructor for the SomeService class.

public SomeService(ISessionStateService sessionStateService)
{
    _sessionStateService = sessionStateService;
 
    if (_sessionStateService != null)
    {
        if (_sessionStateService.SessionState.ContainsKey(SomeValue1Key))
        {
            _someValue1 = _sessionStateService.SessionState[SomeValue1Key].ToString();
        }
        if (_sessionStateService.SessionState.ContainsKey(SomeValue2Key))
        {
            _someValue2 = _sessionStateService.SessionState[SomeValue2Key].ToString();
        }
    }
}

The code simply checks that the SessionState dictionary contains the appropriate keys, and if it does, it restores the values of those keys from the _sessionState.xml file.

Summary

In this blog post I’ve shown how Prism can be used to save and restore state in a service class. This can be accomplished by injecting the SessionStateService into the service class, and saving the required data to the SessionState dictionary of that class. When the app reactivates, following termination, values can be retrieved from the dictionary in the service class constructor.

No comments:

Post a comment