Thinking Out Loud…
I wrote, well mostly ported, an Android app to the Windows Phone (WP7) and I am having a bit of trouble dealing with the navigation model. I have two problems; Tombstoning and passing data between pages.
Tombstoning is a problem that I cannot solve until I improve my navigation model. Currently, I keep track of page to page activity with a stack of activity objects. I always have a traceback of my pages in the activity stack. An activity has a page associated with it so I can check this to determine if I am coming back from another page or just coming back to the same page I was on already.
Coming back to the same page? That doesn’t seem to make any sense until you understand the navigation model. The navigation model is stateless and works like a web page. It is easy to know if you are arriving on a page or leaving a page but where you are coming from is never known. This is why it is tricky to pass data back to a page from another.
This is a data and navigation management nightmare.
A New Solution
I have not given it a lot of thought yet but one solution that I have not tried is to not pass data back from a page. The page should have access to whatever data items are being changed in the system. I really don’t like the idea of a list page knowing about the page that opened the list but I already have some of that knowledge built in right now. All I need to do is change the code so that the list page can always update the data in the system based on the list selection.
So the first change is to make a page always update the data in the system that the page is modifying. The page before it that probably opened it, the new page, won’t do anything special to update any data. This may be a little tricky for the camera task and the bar code reading page but I’ll handle that somehow.
The navigation direction to a page is not too important if the earlier problem of passing information is solved. A page should not need to detect display changes because the data and the display fields on a page are connected and any child page will have already changed the display. The navigation direction is therefore less important than now. If the direction is “back” then it will not matter if navigating from another page in my app or a page of some other app like the lock screen or home page.
Navigating forward to one of my pages will work like it does now with there being an activity object being created to pass data to the child page. This might still be bad since passing binary data to a page doesn’t work right when tombstoning. I am thinking about how the URL for the page should contain text data that can be used to handle the navigation and operations. The page that gets a URL with data will then go get the binary data from global data in the app. There is always global data because of the nature of this app although I would call it app-wide data or app data, not global data.
The page handling code for a page will know if the page is new or if it already exists in binary form. Navigating forward to a page always creates a new page. It never exists before that navigation. Navigating back to the back might be done with the page existing, as is the case of ordinary navigation, or it might not exist, as in the case of the app being tombstoned. Tombstoned is a silly word for an app being placed in a hibernation state. Hibernating is the term used to describe how a system saves the current state of everything and then powers off. An app that is tombstoned is hibernating. The app is responsible for saving its state and that is the tricky issue with hibernation.
The app currently assumes that the state must be saved when navigating forward from a page. I plan on adding code to detect the deactivation event and only saving state upon deactivation. That does not guarantee that the app will get tombstoned but it will make is so that the time needed to save the state is only taken when the app might be tombstoned. An app-wide flag should work for detecting deactivation.
Navigating Forward From a Page
Detect a global flag that indicates if the deactivated state is in effect. If deactivating then save the application state. Don’t save state if not deactivating because it can take a long time to save the state of the entire app.
Navigating Forward To a Page
Use text data in the URL if possible for taking any action. This simplifies coming back from being tombstoned.
If using binary data, use data that can be recreated after coming back from being tombstoned.
Navigating Back To a Page
Detect flag in constructor to know if the page is new. If the page is new then restore the app state.
Navigating Back From a Page
When leaving a page, update all data for the app so that the previous page need not take action. I am not sure if I can do this in every case but it should be possible. It may mean adding code to a page that knows much more about the data in the app than I want it to know!