Author:
Yochay kiriaty
The first two articles (Part 1
And part 2
You have learned about the different events in the application lifecycle, including launching, deactivated, closing, and activated, and their differences. In this knowledge and code
On the basis of, we continue to explore.
Save temporary data and navigate to the correct page
Recall that the second page of our program contains two text boxes, one for allowing users to enter a phone number that will be saved to the contact information, and the other for users to enter a short message to be sent. This is useful when we use the launchers and selector in the tombstone State program.
First, you must clarify the problem. The simplest way is to do a small experiment:
- Open your program in Visual Studio.
- Navigate to the second page and enter some information in the two text boxes.
- This will disable your program (for more information, see the second part of this series ).
).
- Press the return key once to return to your application. This will cause your simulator to display a black screen.
- Press F5 or restart your Visual Studio debugging session in any way to reactivate your program. (Once again, if you miss some content, please refer to the second part of this series)
- Now, your program should be running and you can see the second page of the program. However, the content in the text box is empty. The content you entered before stopping the program is no longer in use. They are gone!
In this small experiment, you can know that the data you input in the program will not be automatically saved when the program is stopped (Remember, your program is terminated. The re-activation means that a new instance of the program is restarted. This indicates that all controls have no data by default, unless you load data for them.
Tombstone programsThe most important
YesUsers can return to your application
, SoYour program may not be reactivated
. If you want it to happen, save any data you want to recover to the disk. Of course, as a developer, it is up to you and your job responsibilities to save and obtain application data.
Let's differentiate the two types of data to be saved (from msdn
):
- Persistent data
-- Data shared by all instances of multiple programs. Persistent data is stored and loaded inIndependent storage Zone
. The setting of each program during execution of different applications is an example of persistent data.
- Temporary data
-- Describe the status data of a single instance of an application. Temporary data is stored in phoneapplicationservice.
Class state
Dictionary. A tombstone program restores its temporary state when it is re-activated.
In the next article, we will explain how persistent data works with an independent storage zone. Now let's focus on how to manage temporary data and use the state dictionary.
A new class in the SDK isPhoneapplicationservice
. It provides access to various states in the application lifecycle. This includes the management of idle programs and the management of Program states. This category plays a leading role in the tombstone game because it discloses launching, deactivate, activated, and closing events, which are stored in the app. XAML. the CS file has corresponding methods (you have already seen them ). This class also includes a read-only typeIdictionary
. The importance of this dictionary is that when your program is processed as a tombstone, it will be persisted in your application by the Windows Phone operating system. When the application is re-activated, objects in the dictionary will be returned. If you only want the application to return from the tombstone status, you do not need to save these temporary objects to the disk. Therefore, if you want to use the State dictionary, make sure that only temporary data is saved in it-data that you don't mind losing or useful only to the current application instance. In our example, we save the phone number and short message content.
Note that the object you saved to this dictionary must beSerializable
(Serializable). Otherwise, you will get an exception about the failure of the operating system to disable or resume the use of your object when the stop event is triggered.
Best Practices in msdn
We recommend that you
Onnavigatedfrom
The temporary page data is saved in the state dictionary inOnnavigatedto
Load data in the event.
I updated the program so that I could save the phone number and short message to this dictionary and load it every time I navigate to the page. The State dictionary is empty when a "complete" new program instance (which means the launching event is triggered) is started.
Protected override void onnavigatedfrom (system. windows. navigation. navigationeventargs e) <br/>{< br/> util. trace ("***** in detailspage: onnavigatedfrom (" + datetime. now. ticks + "*****)"); <br/> // try to locate the phone number from previous SAVE and simply override it <br/> If (true = phoneapplicationservice. current. state. containskey (phonenumberkey) <br/>{< br/> // clear Prev value <br/> phon Eapplicationservice. current. state. remove (phonenumberkey); <br/>}< br/> phoneapplicationservice. current. state. add (phonenumberkey, this. phonenumbertxt. text); <br/> // try to locate the SMS messagefrom previous SAVE and simply override it <br/> If (true = phoneapplicationservice. current. state. containskey (smsmessagekey) <br/>{< br/> // clear Prev value <br/> phoneapplicationservice. current. state. rem Ove (smsmessagekey); <br/>}< br/> phoneapplicationservice. current. state. add (smsmessagekey, this. messagetxt. text); <br/>}< br/> // Step 2 <br/> protected override void onnavigatedto (system. windows. navigation. navigationeventargs e) <br/>{< br/> util. trace ("***** in detailspage: onnavigatedfrom (" + datetime. now. ticks + "*****)"); <br/> // try to locate the phone number from previous run <br/> If (True = phoneapplicationservice. current. state. containskey (phonenumberkey) <br/>{< br/> string S = phoneapplicationservice. current. state [phonenumberkey] as string; <br/> If (! String. isnullorempty (s) <br/>{< br/> util. trace ("***** in detailspage: onnavigatedto: found phone number (" + datetime. now. ticks + "*****)"); <br/> This. phonenumbertxt. TEXT = s; <br/>}< br/> // Step 2 <br/> // try to locate the phone sms msg from previous run <br/> If (true = phoneapplicationservice. current. state. containskey (smsmessagekey) <br/>{< br/> util. trace ("***** in detailspag E: onnavigatedto: Found sms msg ("+ datetime. now. ticks + "*****)"); <br/> string S = phoneapplicationservice. current. state [smsmessagekey] as string; <br/> If (! String. isnullorempty (s) <br/>{< br/> This. messagetxt. Text = s; <br/>}< br/>}
Note the following changes. Page 2 information is saved during navigation switching between pages. That is, when you press the return key on page 2 and the application returns to page 1. If you click the "navigate to next page" button on page 1, your program will navigate to page 2. The onnavigateto event (in page 2) will be triggered, and the code above will load the control data. This is very important because if you carefully observe the output window information of Visual Studio, you will find that every time you navigate to page 2, its constructor will execute. This indicates that the page will be destroyed every time you press the return key in page 2. Therefore, every time you navigate from page 1 to page 2, page 2 will be re-created. If you want to observe this behavior, you can switch between the two pages. Note that the constructor of page 2 is called every time you navigate from page 1 to page 2. If you comment out the content in the onnavigatedfrom method in the program, when switching between pages, you will see that the information on the second page is not saved.
Now you can see that the phone number and short message have been saved when the program is changed to a tombstone, not only when the page is switched, but also when the program is returned after it leaves. Navigate to page 2, enter a phone number and text information, and press the Windows key to change the program to a tombstone. You should be able to see the trace information of the deactivated event and the program is terminated. Press the return key and do not forget to press F5 in Visual Studio to restart the debugging session. Your program will return to the tombstone status, and you will see the activated event is triggered, and then the constructor of page 2. Next, you will see the onnavigatedto information. If everything goes well, you will see the "found phone number" and "found sms msg" lines of information, as shown in.
Now everything is fine. I also want to explain how the tombstone Windows Phone application works. But now it's time to start our game and show some cool content in practice.
First, I added a helper class logger to record all trace information and display them in the text box on the homepage (page 1. The purpose of logger is to prove to you that your application is terminated and the State dictionary is indeed working. This log class also allows you to run applications in non-debug mode of the simulator, and get tracing information and display it in the log text box.
Logger class
The logger class implements a very simple Singleton mode.
(But it may not be thread-safe ). This class is designed as a singleton. When your application ends, only one instance of the class is removed from the memory, in addition, there are related events and data loaded in different events. This class has a string member log and a datatime member to save the creation time of the logger object. Through the logger class, you can add some new lines to the log and obtain the entire log. This is very helpful for debugging, which is also the responsibility of logger. You can add a trail to a logger every time you use the util class.
Generally, the implementation of a single instance does not have a common constructor. However, if you want to save this class to the State subcode, this means that the logger class must be serializable, so there must be a public default (empty) constructor. Otherwise, you will get an exception when you stop or activate the program.
To view the log, I added onnavigatedto to mainpage. XAML. CS and loaded the text in the log to the home page.Logtextbox
Control. Therefore, every time you navigate to the home page of the program, the log file is printed. This allows you to view the tracing information of the program without debugging the program in vs (thanks to Jaime Rodriguez
). Try it now.
- First, deploy your program to the simulator. You can right-click your project in the Solution Explorer panel of Visual Studio, or click "deploy" from the build menu ".
- In the simulator, click the white arrow in the upper right corner of the phone to navigate to the Application List.
- You should see a very short list of applications. Find your program from the list. If you use the code in this article, the application name is lwp. applifecycle.
- After the application is started, you will see the tracking information in the homepage text box. You may want to change the phone settings (click the wrench button) to adjust the scale level of the simulator to 100%. The text in the log text box is very small, so as to display as many historical records as possible without a scroll bar.
- In the log text box, you will see the tracing information of the application creation and homepage constructor.
- Click Next.
- On the second page, enter a phone number or some information.
- Click the Windows key to deactivate your program. In the simulator, you should see the starting interface.
- Click Back to return to your application. This will reactivate your application and restore it to the last browsed page, that is, the second page. If everything goes well, you will see the information you entered in Step 7.
- On the second page, click "back" to return to the first page. The tracking information displayed in the log text box should be consistent:
The most interesting section in the trace information is in the dotted line. The following code snippet comes from the activatedd event of the application.
If (true = phoneapplicationservice. current. state. containskey (loggerkey) <br/>{< br/> logger = (phoneapplicationservice. current. state [loggerkey] As logger); <br/> long timedef = logger. instance. creationtime. ticks-logger. creationtime. ticks; <br/> util. trace ("-----------------------------------/n --> time difference between loggers =" + timedef <br/> + "/N" + logger. getlog () <br/> + "/n -------------------------------------"); <br/>}
In this Code, you will see that we retrieve the logger object in the state dictionary. An object is stored in the state dictionary when the deactivated event is triggered. Assuming that the logger object is found, we create a temporary logger object (note that this is not the logger object we actually use in the current program ). Then compare the creation time of the logger object obtained from the dictionary and the logger object in the just-activated application. As you can see, there is a time difference. When the program is disabled, the logger stored in the state dictionary takes longer time than the new logger. In the code, you can see that we cannot really initialize the old logger; its creation time and log are restored and printed into the text box. Therefore, each line of information in the dotted line depends on the trigger of the disabled event during the last running of the application.
The first line after the dotted line shows the constructor on the second page, which, as expected, indicates that the "new" application is activated and returns to the second page from our disabled application.
Summary
Now you have seen all four events in practice: launching, deactivated, activated, and closing. I want you to know when the program is not running, when it is terminated, and when it will be lost if your data is not saved. In addition, when you return a program, you will get a new instance of the program, whether the activated event or the launching event is triggered (Our Singleton lab has confirmed this ).
The State dictionary can save temporary data in deactivated and activated events, and it is proven to be a very useful tool in the next article we will discuss selector and starter.