The previous post discussed using the Page State Dictionary to restore a page’s state when navigating back to that page following the application being tombstoned. This post will discuss the use of the Application State Dictionary, and the final post in the series will discuss using Isolated Storage.
The Application State Dictionary
The Application State Dictionary has a broader scope for availability than the Page State Dictionary, but still has some similar limitations. It is also implemented as an IDictionary<String, Object>, and is exposed through the PhoneApplicationService instance’s State property. The current instance of the PhoneApplicationService is usually accessed through the class’s Current static property – eg PhoneApplicationService.Current. Any objects stored in the Application State Dictionary need to be serializable. It is important to note that if an item is added to the dictionary when debugging, an ArgumentOutOfRangeException will be raised, but at runtime this exception is silently ignored.
Although the documentation does not call out any specific size limitations, empirical testing has shown there is one of about 1.5MB (it actually varies between the emulator and an actual device.) Storing data larger than that will result in an unhandled COM Exception with the message “The client who called IAccessControl::IsAccessPermitted was the trustee provided to the method” [sic]. This error does not happen immediately, but instead happens when the application is tombstoned, after the Application’s Deactivated event.
The contents of the Application State Dictionary can only be accessed within or after the application’s Activated event has been raised and within or before the application’s Deactivated event has been raised. Any attempt to access the contents outside of these times will result in an InvalidOperationException being thrown. Just like the Page State Dictionary, once these limitations are understood, the use of the Application State Dictionary is straightforward.
private void Application_Deactivated(Object sender, DeactivatedEventArgs e)
{
PhoneApplicationService.Current.State[“MyStuffToSave”] = value;
}
private void Application_Activated(Object sender, ActivatedEventArgs e)
{
if (PhoneApplicationService.Current.State.ContainsKey(“MyStuffToSave”))
{
value = PhoneApplicationService.Current.State[“MyStuffToSave”];
}
}
Because the PhoneApplicationService is available throughout the application via the PhoneApplicationService.Current static property, the Application State Dictionary is available throughout most of the application (though it usually wise to respect proper architectural boundaries and hence be aware of what layer it is being called from.) In that light, the Application State Dictionary can be seen as a kind of globally-scoped collection of name-value pairs.
Both of the State Dictionaries keep their data in memory as opposed to Isolated Storage, which uses the phone’s file system. As a result, access to data is significantly faster. Some quick testing showed this to be ~30% faster on the emulator, and ~55% faster on an actual device, though individual devices are likely to report other results due to hardware differences.
There are some interesting scenarios that this state repository offers, including:
To use the Application State Dictionary to set page values following navigation, instead of using the Page State Dictionary to store a control’s state when leaving a page and to restore the state when returning to the page, the Application State Dictionary can be used, as illustrated in Figure 1, below.
Figure 1
Another scenario where the Page State Dictionary can be used is for passing complex objects between pages. Remembering that navigation between pages on the phone does not involve actually creating an instance in code of the page to navigate to – the call to the Navigate method of the NavigationService with the Uri of the page to navigate to takes care of creating the new page instance. Although data can be communicated between pages via a QueryString parameter, complex data may not translate well to QueryString values. Using the Application State Dictionary to supplement the exchange of data between pages via QueryString information is illustrated in Figure 2.
Figure 2
Finally, the most common use of the Application State Dictionary is to preserve and restore application-scoped state when an application is tombstoned and reactivated. This process is shown in Figure 3.
Figure 3
Another important note is that the application’s Deactivated event handler must complete in 10 seconds or less, or the application might be forcibly terminated and may be unavailable via the back stack.
The Application State Dictionary and Choosers
The term “Chooser” is applied to Windows Phone API elements that allow the user to launch an application that is part of the Windows Phone system in order to make a selection, and upon completion, return that item to the calling program by raising a Completed event. Choosers include:
Choosers are distinguished from Launchers, which allow the application to launch certain Windows Phone system applications in a fire-and-forget model. Some Launchers include the WebBrowserTask, which opens a web browser with the given address, and the EmailComposeTak, which displays a new email message with given values for recipients, message subject, and message body, and there are several additional Launchers.
The guidance given for using Choosers advises that the Chooser’s completed event should be subscribed in the Page’s constructor. This is because when the Chooser is invoked, the running application *might* be tombstoned, losing the event subscription as part of that process. (There is documentation indicating that Choosers have been optimized to not always tombstone an application. Ssee the bottom of the article at http://msdn.microsoft.com/en-us/library/ff817008%28v=VS.92%29.aspx for a description of the optimization that may bypass this…still, since there is a grain of unpredictability, the action needs to be handled as if tombstoning is a certainty.)
The problem with Choosers is that the Completed event is actually raised before the page’s OnNavigatedTo method is called. This means that the Page State Dictionary is not available when responding to a Chooser’s completed event, and attempting to access it will result in an InvalidOperationException. Imagine the following scenario:
Using the Application State Dictionary, the selected item in the list can be saved off while the Email Address Chooser (potentially) tombstones the application and restored when the application returns with the chosen address, as the following code illustrates:
private readonly EmailAddressChooserTask _chooser = new EmailAddressChooserTask();
public Page1()
{
InitializeComponent();
_chooser.Completed += HandleEmailAddressChooserCompleted;
}
private void SendButton_Click(Object sender, RoutedEventArgs e)
{
if (SelectionListBox.SelectedItem == null) return;
PhoneApplicationService.Current.State[“InterestingItemToSend”] = SelectionListBox.SelectedItem.ToString();
_chooser.Show();
}
private void HandleEmailAddressChooserCompleted(Object sender, EmailResult e)
{
if (e.TaskResult == TaskResult.OK)
{
var emailComposeLauncher = new EmailComposeTask
{
To = e.Email,
Subject = “This is Interesting”,
Body =
“Check out this interesting thing” +
PhoneApplicationService.Current.State[“InterestingItemToSend”]
};
emailComposeLauncher.Show();
}
}
So now we’ve seen how the Application State Dictionary adds to the functionality offered by the Page State Dictionary, including exchanging information through several parts of an application, saving application state information across tombstoning events, and how it can be used to allow Choosers to get access to page state information when they return control to the calling application. The next installment will explore support for Isolated Storage in the Windows Phone system.
Microsoft Azure and Amazon Web Services (AWS) are two of the most popular cloud platforms.…
Cloud management is difficult to do manually, especially if you work with multiple cloud…
Azure’s scalable infrastructure is often cited as one of the primary reasons why it's the…
https://www.youtube.com/watch?v=wDzCN0d8SeA Watch our "Unlocking the Power of AI in your Software Development Life Cycle (SDLC)"…
FinOps is a strategic approach to managing cloud costs. It combines financial management best practices…
Using Kubernetes with Azure combines the power of Kubernetes container orchestration and the cloud capabilities…