Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

31 Days of Mango | Day #23: Execution Model

DZone's Guide to

31 Days of Mango | Day #23: Execution Model

· Mobile Zone
Free Resource

Download this comprehensive Mobile Testing Reference Guide to help prioritize which mobile devices and OSs to test against, brought to you in partnership with Sauce Labs.

This article is Day #23 in a series called 31 Days of Mango, and was written by guest author Samidip Basu.  Samidip can be reached on Twitter at @samidip.

Day23-ExecutionModel

Let’s just agree – our smartphones are pretty smart these days. But all the emails, social integration, games & applications do take a toll on the smartphone’s comparatively tiny processing system & memory, but more importantly battery life. It is thus crucial for any mobile OS & third-party applications to be very responsible in optimizing the use of resources in a smartphone, so as to provide the most fluid, responsive, yet lasting user experience. This is where Execution Models come into play & it becomes important to understand the various states/events during an application’s lifecycle. In this article, we talk about what the Execution Model looks like for Windows Phone & what has changed in the Mango release for consumers/developers.

The Windows Phone Way

As we dance between various parts of the Windows Phone OS & third-party applications all day, the phone takes a well-defined approach to managing the lifecycle of applications from launch to termination. The execution model simply allows only one application to run in the foreground at any time. While we shall see how this is beneficial to the user experience, let me play devil’s advocate & argue for the contrary. However, even if it was possible, can you really envision running multiple applications side-by-side in the foreground in a Windows Phone? Isn’t the screen real estate too limited to try doing that? The focus on one application at the foreground simply makes sense for the phone form factor and engages the user in a chrome/distraction free immersive experience. Where this is more real estate to play with, similar Metro UI operating systems do allow multiple foreground applications to be docked side-by-side, as in Windows 8 snapped views. But I digress J

So, this decision of one application on the foreground does have implications on the lifecycle of an application. Most Windows Phone users are very used to quickly moving between 3rd-party applications & the OS itself through the use of Start/Back buttons, Tiles & Toasts etc. Each Windows Phone application goes through several phases, each exposing events, as we cycle through the application’s time in the foreground. Details follow.

The Application States

In essence, each Windows Phone application cycles through the following states:

  • Running – This is the foreground primetime for any application. The OS & the user give the application all the attention to carry out what it does.
  • Dormant – The moment an application steps out of the foreground, it immediately goes into a Dormant stage. This is a new enhancement in Windows Phone Mango, where the whole application with its state & backstack history is kept intact in memory. The goal here is satisfy the supreme responsiveness of applications on resume, which have just fallen out of the foreground, in case the user wants to return to the application. This is what we call Fast Application Switching (FAS) in Windows Phone Mango.

Want to try it? Well, needless to say, you need a Windows Phone running Mango or the latest Emulator. Jump between several parts of the OS or through multiple 3rd party applications, then hold down the Back button .. and voila! You see something like this, don’t you?

FAS

What you are seeing is the Application backstack, an in-memory footprint of applications that are in Dormant state, ready to spring back to the foreground on your one tap. To the consumer, this is multi-tasking. To you as a developer, this is FAS .. a very quick application resume without you having to do anything! Well except for recompiling your pre-Mango applications using the latest Windows Phone SDK 7.1. This immediately has two effects – your application doesn’t show the old “Resuming …” message if coming back to foreground from Dormant state & you also see the application screenshot in the Application backstack. We shall see some code in a bit.

  • Tombstoned - Now, as we saw, the Windows Phone runtime keeps a backstack of in-memory Dormant applications that have recently been on the foreground. While the instant resume is great, any smartphone has limited memory availability and the OS might need support to pull off an expensive operation. Guess what happens next .. yep, applications fall off the backstack in Last-In-First-Out mode! In other words, they are tombstoned & considered to be not consuming any system resources beyond that point. The last statement is technically not entirely true, as we shall see in a minute.

So, how does Tombstoning affect an applications lifecycle? Well, if the user has been using your application, and then went on to a few very resource-intensive games, there is a chance that eventually your application might be tombstoned to release some memory back for system consumption. However, the user might decide to traverse the backstack to get back into your application after a while. How should your application behave? Can we remember things the user was up to when he/she left our application?

The answer is yes! We can absolutely provide the user with an experience that might come across as if he/she never really left your application & start from where they left off. To achieve this effect, however, needs us developers to share some responsibility to manage the state of our application throughout its lifecycle. In the code that follows, we shall see how we can hydrate our application state when resuming an application out of Tombstone, to give the end user the impression that the application never actually got killed. The truth is even when an application in Tombstoned, some little data (as a dictionary) about the state of the application and backstack of pages within the application is preserved in memory by the Windows Phone OS.

  • Terminated – An application in this state has absolutely zero memory footprint on the Windows Phone OS. Nothing, including State dictionaries, which we talk about later, is preserved and any subsequent use of the application results in a fresh instance. An application reaches this stage after it has been Tombstoned or the user back-navigated past the first page or there was an unhandled exception killing the application.

Pages & Events

Before we move on to application lifecycle events, let us take a small step back to make sure our fundamentals are right. All Windows Phone Silverlight applications run as a collection of XAML pages that are loaded inside a Phone Application Frame. While the application is in the foreground, the user is free to navigate between pages inside the application. Hitting the phone's Back button makes the user traverse through a backstack of pages inside an application, until the first page of the application is hit & then next Back key press exits our application. We, as developers, need not do anything to make this happen, as the Windows Phone OS takes care of this automatically during the application's primetime in the foreground.

But consider this .. a user is typing some content in a text input control on one XAML page, gets distracted & actually moves out of our application to carry out some operation. When he comes back, two things might happen. One, the application could have just been Dormant & springs right back into foreground, retaining the exactly what the user was typing .. there is nothing your application needs to do to support this, except for checking on an API to make sure you application was Dormant. Secondly, your application may have been Tombstoned & now you have a little problem. You need to bring your application back to life & hydrate the state of the XAML page to exactly how the user left it .. this we shall see in code.

So, now that we are talking Page States, it is a good time to talk about two events during a page's own life span:

  • OnNavigatedTo - This event fires when the page is being brought to the foreground for display. This provides us developers an opportunity to read query strings passed into the page or hydrate the page controls appropriately if coming out of Tombstone.
  • OnNavigatedFrom - This event fires when the user is leaving the present page to go to another page within the application or leaving the application altogether. In either case, this serves as a good checkpoint to save any state information for the current page, in case restoration may be needed in future. We shall see examples in code.

Data & State Dictionaries

Now, let's take a look at what kind of data we are trying to preserve & hydrate/dehydrate during our application's Execution Model. In my opinion, application data on Windows Phone is of two types:

  • Settings & Permanent Data – This type of data is the crux of your application and needs to be persisted across application runs/instances. We should waste no time in saving such data straight to Isolated Storage, either as Name/Value pairs or Files/Directories, or in SQL CE if the data is relational.
  • Page & Transient Data ­– This is the expendable, but convenient to save data & is mostly dealt with in memory. This type of data could be anything ranging from user-entered unsaved data on a page or some ViewModel or some temporary data per application lifecycle, fetched from outside. This is the data we need to handle carefully to give the end users an impression that our application is alive & kicking throughout its lifecycle. Now, we have some help. Windows Phone OS exposes a Dictionary to each application & each application page that could be used to store serializable Key-Value pair data. This State dictionary is off of the PhoneApplicationService and should only be used to store transient state data. You should not use this property for excessive storage because there is a limit of 2 MB for each page and 4 MB for the entire application; but as we shall see in code, this is rather helpful in maintaining state during our application’s execution model. And it is these dictionaries that are persisted by the Windows Phone OS even after our application has been tombstoned. If the application is reactivated from Tombstone, this state dictionary will be populated with the data we saved in it during application’s Deactivation. Because this data is present in memory, we can use it to restore state without resource-intensive file operations.

Application Events

Now that we know all the details & the inside workings, let’s just see when we do what during an application’s lifecycle. The PhoneApplicationService raises 4 primary events during an application’s execution model that helps us manage state:

· Launching – This event is raised when a new application instance is created by user actions like launching from application list, or by tapping on Tile/Toast or other means. In this case, we begin with a fresh slate, and not as any continuation of past application lifecycles.

· Deactivated – This event is raised when the users navigates away from our application or a Chooser is launched. This is the best opportunity for us to save the state of the application into the State dictionary for future use in resuming the application. If resumed from Dormant state, this would not be necessary; but absolutely needed if resuming from Tombstone and the Deactivated event is the only chance we shall get to save application-level state.

· Activated – This event is fired when the application is returning to the foreground, either from being Dormant or Tombstoned. Guess what .. a simple API flag called the IsApplicationInstancePreserved off of the event args tells us what state our application is resuming from. If the flag is true, our application has just been Dormant & held in memory; so no action is required and FAS kicks in. If the flag is false, we are returning from Tombstone & would use the state dictionary to restore application state.

· Closing – This event fired when the user traverses through the application’s page backstack & past the first application page. At this point, the application should have exited the foreground & terminated itself after raising an event. No state information is preserved on termination and subsequent launches of the application would result in fresh instances.

As a common theme, heavy resource intensive tasks should be avoided during any of the above application events, since we have a limited amount of time (10 seconds to be precise) that the OS would wait for our methods to finish. For best user experience, some of the expensive operations of maintaining state should be performed on background threads while the application is running.

Want to make sense of all of the above information? Well just take a look at the overall Execution Model diagram for Windows Phone, best described by an MSDN article:

Execution Model

[Courtesy MSDN]

Demo Application

We have been all-talk so far, haven’t we? Let’s see some code! We’re going to build a simple Windows Phone application that highlights state management across the application’s lifecycle. The entire built application is available for download at the end of the article; just make sure you have Windows Phone SDK 7.1, grab the bits & hit F5!

So, let’s begin. File -> New & we accept the most basic default template for an application with one XAML page only, that being MainPage.xaml/cs. We are going to open up the XAML page & drop some demo controls for our sake. The end state is something like this (click to enlarge):

XAML Page

Here’s the goal .. we are going to split up the controls to manage states of various types of data, as described below:

  • App Setting – This is an example of an application level setting that has to be persisted across application instances. Most common example would be a user setting for your application.
  • App Transient Data – This set of controls will simulate application level data that is only applicable per application instance, but may be usable in multiple XAML pages throughout the application. Best such example would be some web service data that an application fetches every time it runs afresh.
  • Page Transient Data – This set of controls stands for page specific control data that we possibly do not want to lose if the user steps out of our application & comes back to it through application backstack.


We’re going to handle each type of data separately. So, let’s start with the App.xaml.cs – the place to handle global application logic/data. Let’s add some custom properties/initializers, along with a little code in the Constructor:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO.IsolatedStorage;

using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace Day_24___Execution_Model
{
    public partial class App : Application
    {
        public PhoneApplicationFrame RootFrame { get; private set; }

        public bool AppSetting { get; set; }
        public string AppData { get; set; }

        public static new App Current
        {
            get { return Application.Current as App; }
        }

        // Constructor.
        public App()
        {
            // All other initialization code ..
            AppData = string.Empty;

            if (IsolatedStorageSettings.ApplicationSettings.Contains("AppSetting"))
            {
                AppSetting = (bool)IsolatedStorageSettings.ApplicationSettings["AppSetting"];
            }
        }
    }
}
 

Next, we’re going to add some code to application’s lifecycle event handlers. Notice the use of the IsApplicationInstancePreserved flag to decide whether we are coming out of Dormant/Tombstoned state in the application’s Activated event handler. Now, I didn’t have a good reason to add any special code to the application’s Launching/Closing event handlers; but you are free to if your application needs any such code. Also, notice the use of the State dictionary off the PhoneApplicationService:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO.IsolatedStorage;

using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace Day_24___Execution_Model
{
    public partial class App : Application
    {
        public PhoneApplicationFrame RootFrame { get; private set; }

        public bool AppSetting { get; set; }
        public string AppData { get; set; }

        public static new App Current
        {
            get { return Application.Current as App; }
        }

        // Constructor.
        public App()
        {
            // All other initialization code ..
            AppData = string.Empty;

            if (IsolatedStorageSettings.ApplicationSettings.Contains("AppSetting"))
            {
                AppSetting = (bool)IsolatedStorageSettings.ApplicationSettings["AppSetting"];
            }
        }

        private void Application_Launching(object sender, LaunchingEventArgs e)
        {
        }

        private void Application_Activated(object sender, ActivatedEventArgs e)
        {
            if (e.IsApplicationInstancePreserved)
            {
                // Returning from Dormancy.
                // Do nothing.
            }
            else
            {
                // Returning from Tombstone.
                if (PhoneApplicationService.Current.State.ContainsKey("AppData"))
                {
                    AppData = PhoneApplicationService.Current.State["AppData"].ToString();
                }
            }
        }

        private void Application_Deactivated(object sender, DeactivatedEventArgs e)
        {
            PhoneApplicationService.Current.State["AppData"] = AppData;
        }

        private void Application_Closing(object sender, ClosingEventArgs e)
        {
        }

        // Other auto-generated code here ..
    }
}
 

Now, back in our MainPage.xaml’s code-behind, let’s add event handlers for the page’s loading event & the click of the button to fetch some data (which we totally fake), as well as the application setting checkbox’s state being changed. Notice how we hang on to the fetched data at the application level and also how we immediately save application/user settings in the phone’s Isolated Storage:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO.IsolatedStorage;

using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace Day_24___Execution_Model
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor.
        public MainPage()
        {
            InitializeComponent();
        }

        private void chkAppSetting_Tap(object sender, GestureEventArgs e)
        {
            // Store App Setting changes immediately in Isolated Storage for persistence.
            if (IsolatedStorageSettings.ApplicationSettings.Contains("AppSetting"))
            {
                IsolatedStorageSettings.ApplicationSettings.Remove("AppSetting");
            }

            if ((bool)this.chkAppSetting.IsChecked)
            {
                IsolatedStorageSettings.ApplicationSettings.Add("AppSetting", true);
            }
            else
            {
                IsolatedStorageSettings.ApplicationSettings.Add("AppSetting", false);
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.txtAppData.Text = "This is some sample data ..";

            // As if we are caching the data.
            App.Current.AppData = this.txtAppData.Text;
        }

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            this.chkAppSetting.IsChecked = App.Current.AppSetting;
        }
    }
}
 

Now, let’s add the all-important page navigation events. This is where we get to control how we hydrate/dehydrate transient data as the XAML page comes to the foreground & moves out of it:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO.IsolatedStorage;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace Day_24___Execution_Model
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor.
        public MainPage()
        {
            InitializeComponent();
        }

        private void chkAppSetting_Tap(object sender, GestureEventArgs e)
        {
            // Store App Setting changes immediately in Isolated Storage for persistence.
            if (IsolatedStorageSettings.ApplicationSettings.Contains("AppSetting"))
            {
                IsolatedStorageSettings.ApplicationSettings.Remove("AppSetting");
            }

            if ((bool)this.chkAppSetting.IsChecked)
            {
                IsolatedStorageSettings.ApplicationSettings.Add("AppSetting", true);
            }
            else
            {
                IsolatedStorageSettings.ApplicationSettings.Add("AppSetting", false);
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // Fake data fetch..
            this.txtAppData.Text = "This is some sample data ..";

            // As if we are caching the data.
            App.Current.AppData = this.txtAppData.Text;
        }

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            // Load user setting from Isolated Storage.
            this.chkAppSetting.IsChecked = App.Current.AppSetting;
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            // Load in App Data, if available.
            if (App.Current.AppData != null && App.Current.AppData != string.Empty)
            {
                this.txtAppData.Text = App.Current.AppData;
            }

            // Load any Page State, if available.
            if (PhoneApplicationService.Current.State.ContainsKey("PageData"))
            {
                this.txtPageData.Text = PhoneApplicationService.Current.State["PageData"].ToString();
            }
            if (PhoneApplicationService.Current.State.ContainsKey("PageSetting"))
            {
                this.chkPageSetting.IsChecked = (bool)PhoneApplicationService.Current.State["PageSetting"];
            }
        }

        protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedFrom(e);

            // Clear past state, if any.
            if (PhoneApplicationService.Current.State.ContainsKey("PageData"))
            {
                PhoneApplicationService.Current.State.Remove("PageData");
            }

            if (PhoneApplicationService.Current.State.ContainsKey("PageSetting"))
            {
                PhoneApplicationService.Current.State.Remove("PageSetting");
            }

            // Save off Page state.
            PhoneApplicationService.Current.State["PageData"] = this.txtPageData.Text;
            PhoneApplicationService.Current.State["PageSetting"] = this.chkPageSetting.IsChecked;
        }
    }
}

That’s it! We have now added enough code so that the different types of data/state are managed across the lifecycle of the application, each in a different way as appropriate. Go ahead & give it a spin. Start the application, make setting changes, go somewhere else & come back, or exit & run fresh instance of the application. Data & state information should be preserved and wiped as expected. A typical run with settings turned on looks something like this:

App and Page State

Now, you might notice one thing on both the emulator or if deployed to an actual phone. As we cycle through the application, step out & then return to it in the Windows Phone Mango runtime, it is hard to predict when our application would actually be tombstoned. Most times, if deactivated, the application simply sits in Dormant state & comes right back to life. So, although we have code to hydrate settings when coming back from Tombstone, there is not definite way to test it.

Worry not! There is a simple debug setting that is going to forcibly tombstone your application the moment it deactivates. So, even if the application can stay Dormant, this setting, shown below, forces it to be tombstoned. This obviously helps our testing.

Tombstone Setting

Summary

Adding breakpoints to various event handlers and seeing when they fire during an application’s lifecycle, is a great way to understand the Execution Model. So, what are you waiting for? Go ahead and make full use of the Fast-Application-Switching and hydrate/dehydrate your application/page state correctly throughout the lifecycle of the application.

Result – Happy users, and ultimately happier you!  Adios!

To download a complete Windows Phone project that includes all of the concepts covered in this article, click the Download Code button below.

download

Tomorrow, Chris Koenig is going to talk about another great tool available to us in Visual Studio 2010, the Silverlight Performance Analysis Tool.  See you then!

toolsbutton


Source: http://www.jeffblankenburg.com/2011/11/23/31-days-of-mango-day-23-execution-model/

Analysts agree that a mix of emulators/simulators and real devices are necessary to optimize your mobile app testing - learn more in this white paper, brought to you in partnership with Sauce Labs.

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}