If I can build a phone app anyone can: Part 3 What the heck is tombstoning?
Every time I start digging through Windows Phone stuff I find a blog or video about tombstoning (well okay not that kind). Now that I have my Hello World App I am ready to figure out what the heck tombstoning is! If you want to build an app you will need to know it, if you don’t have tombstoning, your app might not be accepted in the marketplace. So today I’m going to figure this out!
For those of you just joining, I am learning to build a phone app from scratch. If you can code you can build a phone app. The first two blogs in the series will get you started if you need help.
So apparently tombstoning is all about making sure your app gives the user a nice experience if they have to do something like answer a call on their phone (I know, who ever uses their phone for phone calls anymore, let’s say you have to answer a text message, that’s more realistic). You wouldn’t want a user to enter a bunch of information on the screen painstakingly done on a tiny keyboard, leave the page to send a text, come back and have to enter it all over again! That would not make you popular! So tombstoning is about making sure when you come back to the app everything is the way you left it.
At the end of our Hello World app we had a page with a textbox, button, and textblock that looked like this
So If I type Susan into the textbox, hit the Windows key, yup I leave the application, then I hit the Back button and I am back at the application and hey it remembers the value in my text box! Sweet! So I guess I don’t have to worry about writing any code for tombstoning. I know in the pre-Mango applications it didn’t work this way, because your application was deactivated when you left and it didn’t remember state. But they fixed that in Mango. This could be my shortest blog post ever! But no… you see what happened, is when I pressed the window button and went back to the menu, my app was deactivated and became dormant. When I tapped the back button to return to my app it became active again. Here’s a diagram I found that describes what my mango phone application is doing.
BUT!!!! Yes there is a but, the phone can’t just leave all applications in memory forever, that would make the other applications run really slow, and drain battery power. So what happens is the phone keeps an eye on the memory and if there is too much running on the phone it will “tombstone” your application. When that happens it won’t remember stuff like what you had typed into a text box. Here is another diagram I found that shows the extra bubble for tombstoned.
But how the heck do you test this? If the phone decides when it is going to tombstone an app instead of just leaving it dormant, how on earth do I write code to say “if the app was tombstoned go get the values the user entered and put them back in the text box again” and how do I test that if I don’t have a phone? Turns out they thought of that. If you go to the Solution Explorer windows, right click on your project and go to Properties.
When you get to the project properties choose Debug and select the checkbox that says Tombstone upon deactivation while debugging.
Now if I use the Windows button to exit my application in the simulator it will tombstone my app so I can test my tombstoning logic in my application to make sure it will work in case a phone device does tombstone my app behind the scenes.
So let’s see what happens now when I run my application, and then use the Windows button to exit and the Back button to return to my application and sure enough, the name I had typed into the text box is gone!
Okay so now I can see the problem users will have if I don’t do tombstoning. Users who leave my app to do something else on the phone don’t want to come back and lose everything they had typed in. I found a great big MSDN article on how to preserve and Restore Page State, I’ll try to break it down to the basic concepts here, but feel free to go read the article.
So after a little digging I discovered that the best place to remember what someone typed in is in the OnNavigatedFrom event handler of the page. This event fires when you leave the page in your application. To get to the code for your page so you can add the event handler you can right click on the background of the page where you see your screen and choose View code, or in Solution Explorer you can expand your page by clicking on the little arrow so you see the code-behind page listed in Solution Explorer. You can then double click on the code behind page to navigate to the code
Now I can add a OnNavigatedFrom event handler, the syntax is a little different in VB and C#. What I want to do is remember the value the user typed into my text box when I leave the page. After a little digging I found that you can use the State dictionary to remember the values. Basically you call the Add method of the State dictionary and tell it the value you want to store, and what you want to call the value stored so you can get it back later. Call the add method once for each value you want to remember. You do need a little error handling though in case the value is already stored, so I added a little logic that says if the value is already there, delete it and add it back with the new value. When I am done my code looks like this:
Protected Overrides Sub OnNavigatedFrom(e As System.Windows.Navigation.NavigationEventArgs) MyBase.OnNavigatedFrom(e) If Me.State.ContainsKey("NameEntered") Then Me.State.Remove("NameEntered") End If Me.State.Add("NameEntered", TxtName.Text) End Sub
Now I need to add code so that when they come back to the page it reads the value I saved and puts it back in the textbox again. I do this in a OnNavigatedTo event handler. Again I add a little bit of error handling because if someone enters the app for the very first time there won’t be a value stored in state yet, and I don’t want that to crash my application, so basically I say if you find a value go get it and put it in the text box. The code looks like this:
Protected Overrides Sub OnNavigatedTo(e As System.Windows.Navigation.NavigationEventArgs) MyBase.OnNavigatedTo(e) If Me.State.ContainsKey("NameEntered") Then TxtName.Text = Me.State("NameEntered") End If End Sub
Now to test it! Run the application, use Windows button to exit, back to return and Woo hoo! I have successfully told my phone application to remember the value even if it gets tombstoned. If you see a little '”resuming…” message then you know for sure your application was tombstoned, but depending on how long it takes to restore your application you may not see the message.
Now, the programmer in me has one issue with the code I just wrote. Most of the time, my application will not be tombstoned it will just be dormant. So I now have code that runs 100% of the time as you enter and leave the page, but really only needs to run some of the time. Not the best performing code! It turns out you can actually find out programmatically if your application was tombstoned and then you should only restore state IF it was tombstoned.
If you go to the application code page (go to solution explorer, expand the little arrow pointing to App.xaml, and you will see App.xaml.vb or App.xaml.cs, double click on that .vb or .cs file to get to the application code page). By the way there is a whole lab on how to do this tombstoning stuff you can download as well if you want.
If you scroll down through the code you will find a Application_Activated event this is where we can check to see if the application was dormant or tombstoned, because this event receives an argument called IsApplicationInstancePreserved which will be true if the app was dormant, and false if the app was tombstoned. The problem I have though is that I need to be able to find this out in my OnNavigatedTo event handler on the page. There may be more clever ways to do this (open to suggestions from the peanut gallery here) but what I am going to do is create a class called Statemanager with a shared/Static property called restorestate that I can set in the Activated event and read in the OnNavigatedTo event.
Private Sub Application_Activated(ByVal sender As Object, ByVal e As ActivatedEventArgs) If e.IsApplicationInstancePreserved Then StateManager.RestoreState = False Else StateManager.RestoreState = True End If End Sub
Visual Studio Tip: I could create the class before I create the event, but when I get the squiggly under the class name, i just hover the mouse over the little red line (or click on that line and then do CTRL + . on the keyboard, that’s a period by the way) and a little pop-up menu appears that offers to generate the class for me since it doesn’t exist. I choose Generate Class StateManager from the pop-up menu and voila Visual Studio makes the class for me. of course then it complains that the property RestoreState does not exist, so I use the same little trick, click on the line with the squiggly do my CTRL + . and pick Generate field for StateManager (yeah I could do a property here instead of a field, I am just being lazy, I know that in good OO design you always have properties, but this is just a hello world application right now). But I love this little feature in Visual Studio that generates classes, properties, and method stubs for me .
I can now double click on my StateManager class to edit the code, or if you didn’t use the little tip above you could have created the StateManager class yourself by right-clicking the project HelloBonjour and choosing Add Class to create the class from scratch myself and added a shared/static field for RestoreState. Either way, when you are done Your class should look something like this:
Class StateManager Friend Shared RestoreState As Boolean End Class
Now I can go back to my OnNavigatedTo event handler and specify to only load state if RestoreState is true.
Protected Overrides Sub OnNavigatedTo(e As System.Windows.Navigation.NavigationEventArgs) MyBase.OnNavigatedTo(e) If StateManager.RestoreState Then If Me.State.ContainsKey("NameEntered") Then TxtName.Text = Me.State("NameEntered") End If End If End Sub
That’s it that’s all and that’s definitely more than enough for this blog post, time to pat myself on the back for figuring out yet another step in the steps towards building a windows phone app. You know I am beginning to believe I can do this! The whole tombstoning thing always had me confused, I feel a lot better now that I have that piece figured out.