Preserving & Restoring Application State for Silverlight Based Windows Phone Apps

Introduction

The application tenure on mobile platforms is not very long. Frequently, users have to stop doing what they are currently doing on their mobile device and take that all important call. As a Windows Phone platform developer, if you do not account for such scenarios, your product will not appeal to the users if it loses customer data or does not remember what you were last doing in that application. This can get serious for gamers as well, who would have to start the game from the beginning, if the game could not store progress.

When to Note Application State

It is important to realize that at certain events, it is critical to note the application state. The main events where preserving and restoring state is critical are: application launch (Launching), application activation (Activated), application deactivation (Deactivated) and application termination (Closing).

Storage Facilities in the Windows Phone Platform

The Windows Phone platform allows applications to store its information at the following two locations:

IsolatedStorage: This is an isolated area for storage which only this application has access to. This ensures privacy of the data. This storage is persistent so it can be accessed across instances of the application.

State dictionary: This is a non-persistent storage location which is available only as long as the phone is either active or in the tombstoned state. This storage location is exposed as is the State property of the PhoneApplicationService object which can be accessed by the main class of the application. Since this storage is non-persistent, this data is not available if the application is terminated and re-launched.

Only data which can be serialized can be stored in the State dictionary.

Hands On

Let’s use a hands-on example to illustrate how to preserve and restore application state.

Start Microsoft Visual Studio and create a new Silverlight for Windows Phone project and call it WindowsPhoneApplicationContextDemo. Start off by adding a string to represent the application data, and call it myAppDataContext. You will add this in the App call (App.xaml.cs):

  public partial class App : Application
  {
  public string myAppDataContext;
   }

You will note that in this class, there are already event handlers for the various interesting application events (Application_Lauching, Application_Activated, Application_Deactivated and Application_Closing).

Note in the Application_Launching event hander, you do not want to do anything since this is the first time the application is launched and state is not available.

However, things get interesting with the Application_Activated event. In the event handler for that event, we check to see if state exists in the State Dictionary. If it exists we can set our application data object to that value.

           // Code to execute when the application is activated (brought to foreground)
           // This code will not execute when the application is first launched
           private void Application_Activated(object sender, ActivatedEventArgs e)
           {
               if (PhoneApplicationService.Current.State.ContainsKey("myAppDataContext"))
               {
                   myAppDataContext = PhoneApplicationService.Current.State["myAppDataContext"] as string;

               }

           }
 

Now, we add code to capture application context when the application is deactivated. We can also use this event to store the application context to a persistent storage like IsolatedStorage.

           private void Application_Deactivated(object sender, DeactivatedEventArgs e)
           {
               // If there is data in the application member variable...
               if (!string.IsNullOrEmpty(myAppDataContext))
               {
                   // Store it in the State dictionary.
                   PhoneApplicationService.Current.State["myAppDataContext"] = myAppDataContext;

                   // Also store it in Isolated Storage.
                   IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
                   StreamWriter sw = new StreamWriter(isoStore.OpenFile("myAppDataContextFile.txt", FileMode.OpenOrCreate));
                   sw.Write(myAppDataContext);

               }

           }
 

Sometimes, a user can accidentally hit the back button when on the first page of an application. In such scenarios, we don’t need to update the application data context , but only save it to the persistent storage. We use the Application_Closing event for this.

   private void Application_Closing(object sender, ClosingEventArgs e)
           {
               if (!string.IsNullOrEmpty(myAppDataContext))
               {
                   IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
                   StreamWriter sw = new StreamWriter(isoStore.OpenFile("myAppDataContextFile.txt", FileMode.OpenOrCreate));
                   sw.Write(myAppDataContext);
               }

           }
 

Now that we have updated the App class to work with the interesting event, we can update the Page class.
We will need a way to track if data needs to be reloaded in the page or not. Add a Boolean called newInstance to track this.

   public partial class MainPage : PhoneApplicationPage
       {
           bool newInstance = false;
           string mainpageDataContext;

   In the constructor, set the value of the tracking Boolean to true.
           public MainPage()
           {
               InitializeComponent();
               newInstance = true;
           }
 

Next we override the OnNavigateTo event like we did in the example for the “page state preservation’ article.
Here we add the appropriate code to either retrieve data from the persistent storage if the page has loaded for the first time or from the State dictionary otherwise. I have put the placeholders in the snippet below. The exact code to be put is left as an exercise for the viewers.


   protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
           {
               // Call the base implementation
               base.OnNavigatedTo(e);

               // If this is a new page instance, the data must be retrieved in some way
               // If not, the page was already in memory and the data already exists
               if (newInstance)
               {

                   // Here you will add code to retrieve the data from the persistent storage if this is the first time the application page is invoked.

               }
               else
               {
                   // Otherwise set the page's data object from the application member variable
               }

               // now set the tracking boolean to false since we have already fetched the data
               newInstance = false;
           }
 

Summary

In this article, we saw how to preserve and restore application state either persistently or non-persistently.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read