Windows 8 Metro development FAQ (6)-app suspension status

Source: Internet
Author: User

The pending status of the APP has been mentioned in the previous two blogs about navigation. Let me say that the current version (including the latest RTM version) has a bug. I will show you the bug below. Before that, let me talk about the clinical manifestations of this suspension problem.
I don't know if you have noticed that when you open an app, you browse it for a while and then switch to another app, when you switch back to the original app after a while, you will find that the original app is back to the home page, not the page when you leave the app. There are two reasons for this. This is called "suspend and close" in debugging. It is very easy to check whether the app is in this status. A list of all opened apps is displayed on the left of the screen, if the thumbnail of an app changes to the startup page icon, it indicates that the app is in this status. If the thumbnail of the app is the page when you leave the app, the app is running normally. Next I will introduce the cause of the problem mentioned above.

1. During app development, there is no pending process.

2. the app is suspended during development, but a system bug causes the app to crash when it is suspended. Therefore, when you recover from the suspended status, you can only start from the homepage because there is no data recovery.

The crash API is frame. getnavigationstate () method (This bug is triggered only when the parameters you pass in the navigation are complex types. This is the problem I mentioned in the previous two blogs.If you use the vs Project template, the saveframenavigationstate method in the suspensionmanager class will call the frame. getnavigationstate () method. The main function of this method is to save the navigation status of the frame, so that the app can restore the status correctly when you resume from the suspended status,That is, when you exit the app, which page will be on that page when you return (this is very important, if you haven't recovered the navigation status, it can be said that even if your data is saved, it is useless, because the app will not use the data you saved during restoration)To restore the navigation status, call frame. setnavigationstate.

I will demonstrate this bug below.

First, use vs to create a gridapp project.

Because the parameter types passed on the three pages of the Project template are strings, this problem does not occur. here we need to make some changes. First, modify the itemview_itemclick method in groupeditemspage.CodeThe original code is:

 
VoidItemview_itemclick (ObjectSender, itemclickeventargs e ){//Navigate to the target page and//Configure a new page by passing in the required information as a navigation ParameterVaRItemid =(Sampledataitem) E. clickeditem). uniqueid;This. Frame. navigate (Typeof(Itemdetailpage), Itemid );}

Now we want to change it

VoidItemview_itemclick (ObjectSender, itemclickeventargs e ){//Navigate to the target page and//Configure a new page by passing in the required information as a navigation ParameterThis. Frame. navigate (Typeof(Itemdetailpage), E. clickeditem );}

The original ID is passed directly to the object. Next we need to change the code of the loadstate method in itemdetailpage. The original code is as follows:

    Protected   Override   Void Loadstate (Object navigationparameter, Dictionary <string, Object>Pagestate ){  //  Allow the saved page status to override the initial items to be displayed              If (Pagestate! = Null & Pagestate. containskey ( "  Selecteditem  "  ) {Navigationparameter = Pagestate [ "  Selecteditem  "  ];}  // Todo: create a suitable data model for the problem domain to replace the sample data.              VaR Item = Sampledatasource. getitem (string) navigationparameter );  This . Defaultviewmodel [ "  Group  " ] = Item. Group;  This . Defaultviewmodel [ "  Items  " ] = Item. Group. items; This . Flipview. selecteditem = Item ;} 

The Code is as follows:

      Protected   Override   Void Loadstate (Object navigationparameter, Dictionary <string, Object> Pagestate ){  //  Todo: create a suitable data model for the problem domain to replace the sample data.              VaR Item = (Sampledataitem) navigationparameter;  This . Defaultviewmodel [ " Group  " ] = Item. Group;  This . Defaultviewmodel [ "  Items  " ] = Item. Group. items;  This . Flipview. selecteditem = Item ;} 

 

Now you can run the task directly. After running the task, click an item to go to the details page. The following describes the pending status of debugging.
During debugging, right-click the vs toolbar and a toolbar list will be displayed. The toolbar for debugging is selected (the status is not selected by default ),

Click "suspend and close" to debug the pending status ",

At this time, a problem occurs, and the app directly crash

Because the saveasync method calls the crash caused by the frame. getnavigationstate method I mentioned earlier, you can set the breakpoint on your own. Since frame. getnavigationstate is a bug, you can say that the app you developed is almost impossible to achieve data storage and recovery. In fact, many apps in the store currently have this situation. If you do not talk about it outside of China, I only talk about it in China, this is basically the case for many apps in China (including an app I am currently developing). As long as the app is suspended, it starts from the homepage when you switch back. Here we will talk about the time when the app will enter the pending status, which is determined by the system. If the memory is insufficient, other apps except the currently running ones will definitely enter the pending status.

Is there a solution to this problem? The answer is yes, but it is not perfect. I will discuss how to solve this problem later.

Since our parameters cannot pass complex types, only simple types can be passed or no parameters can be passed. The method I currently provide is "Do not pass Parameters". The "do not pass Parameters" mentioned here is not true, but we need to change the method for passing parameters, that is, we are using frame. parameters are not passed when the navigate method is used. You can only write one method for passing parameters.

When we use the templates provided by Vs to create a project, there will be a common folder with a layoutawarepage class, which is also the base class of the page we created, we need to modify this class to achieve our goal. First, we need to add two methods in the class layoutawarepage. The Code is as follows:

    Private   Static   Object  Nextpageparam; ///   <Summary>          ///  If the passed object is of a complex type, use this method to navigate the page  ///   </Summary>          ///   <Param name = "pagetype"> </param>          ///   <Param name = "OBJ"> </param>          Public   Void Navigate (type pagetype, Object  OBJ) {nextpageparam =OBJ;  This  . Frame. navigate (pagetype );}  Public   Void  Navigate (type pagetype ){  This  . Frame. navigate (pagetype );} 

The code in the onnavigatedto method should be modified below, so that we can pass the parameters correctly and save the parameters we passed so that the original parameters can be used when the page is restored. The Code is as follows:

 

        Protected   Override   Void  Onnavigatedto (navigationeventargs e ){ //  Returning to the cache page through navigation should not trigger status Loading              If ( This . _ Pagekey! = Null ) Return  ;  VaR Framestate = suspensionmanager. sessionstateforframe ( This  . Frame );  This . _ Pagekey = "  Page-  " +This  . Frame. backstackdepth;  If (E. navigationmode = Navigationmode. New ){  //  When adding a new page to the navigation stack, clear  //  Existing Status                  VaR Nextpagekey = This  . _ Pagekey;  Int Nextpageindex = This . Frame. backstackdepth;  While  (Framestate. Remove (nextpagekey) {nextpageindex ++ ; Nextpagekey = "  Page-  " + Nextpageindex ;}  //  If nextpageparam is not empty, we need to save this parameter so that it can be restored normally.                  If (Nextpageparam! = Null ){  String Key = This . _ Pagekey + "  _ Nextpageparam  "  ; Framestate [Key] = Nextpageparam;  This . Loadstate (nextpageparam, Null  ); Nextpageparam = Null ;}  Else                  //  Pass navigation parameters to the new page                  This . Loadstate (E. parameter, Null  );}  Else  {  String Key = This . _ Pagekey + "  _ Nextpageparam  " ;  If  (Framestate. containskey (key )){  This . Loadstate (framestate [Key], (Dictionary <string, Object>) framestate [ This  . _ Pagekey]);}  Else                  //  You can use the same policy to load the pending status and recreate the cache.  //  Discard page, pass navigation parameters and retain Page Status  //  Give page                 This . Loadstate (E. parameter, (Dictionary <string, Object>) framestate [ This  . _ Pagekey]) ;}} 

You only need to replace the original code with the above Code. Next we need to modify the called method, or modify the itemview_itemclick method in groupeditemspage, and set the original this. frame. navigate (typeof (itemdetailpage), E. clickeditem); change to the current this. navigate (typeof (itemdetailpage), E. clickeditem); because the navigate method is added to the base class, we can directly use this. if you try to run the app, you will find that it is still crash, but the reason for the crash is different. The error message returned by this crash is that the object sampledataitem cannot be serialized. Why cannot I serialize the sampledataitem object? Suspensionmanager uses datacontractserializer to serialize a dictionary set and save it to a file. The dictionary type is dictionary <string, Object>, that is to say, when serializing a dictionary, suspensionmanager does not know the type of the dictionary. In this case, you need to manually add knowntypes, that is to say, we need to add all the types saved to the dictionary to the knowntypes set, so that suspensionmanager can serialize the set correctly during serialization. Here I select the set in app. add in CS, add in onlaunched method of APP, suspensionmanager. knowntypes. add (typeof (data. sampledataitem); add this code.

Suspensionmanager. registerframe (rootframe, "  Appframe "  ); Suspensionmanager. knowntypes. Add (  Typeof  (Data. sampledataitem ));  If (ARGs. previusexecutionstate = Applicationexecutionstate. Terminated ){  //  Restores the saved session status only when appropriate.                      Try  {Await suspensionmanager. restoreasync ();}  Catch (Suspensionmanagerexception ){  //  An error occurred while restoring the status.  //  Assume that there is no status and continue  }} 

This is not complete yet, because only the classes marked with [datacontract] can be serialized (including all parent classes, since [datacontract] is marked, attributes must be marked. Otherwise, unlabeled attributes will not be serialized. For those who have worked on WCF, they will certainly be familiar with how to mark it. You can run it directly after marking it. You will find that it can be suspended normally now. And the page at the time of departure, and the page at the time of return.

In fact, the mark here is a bit complicated. Because sampledomainroup and sampledataitem involve circular references, it is useless to Directly mark with [datacontract]. You must mark it with [datacontract (isreference = true. For more information, see my source code.

 

Well, the data storage content is coming to an end here.

 

Click Download source code

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.