Windows 8 應用通常涉及到兩種數據類型:應用數據與會話數據。這篇主要講解會話層面,會話層的數據是基於用戶每次使用應用而形成,這些數據可能不需要留存在設備中。在整個應用生命周期中,應用啟動后便進入運行狀態。當用戶離開或系統進入待機狀態時,應用會進入掛起狀態,此時應用將被放入到內存中,待用戶重新使用時便會恢復成運行狀態。
接下來,我們主要來實現如何在掛起時,實現數據的保存。
新建項目中,添加一個基本頁面,不能添加空白頁面,因為在添加基本頁面時,項目中會自動添加幾個文件,這些文件存放在Common文件夾下:
這里主要用到的是LayoutAwarePage.cs(用於導航和進程生命期管理的狀態管理)和SuspensionManager.cs(捕獲全局會話狀態以簡化應用程序的進程生命期管理)文件。
1.接下來我們將進行應用掛起處理。
1)打開App.xaml.cs 程序,在OnLaunched 方法中創建了rootFrame,當rootFrame 為Null 時將重新創建Frame,在這個邏輯判斷中要使用SuspensionManager.RegisterFrame 方法進行rootFrame 注冊,這樣才可以使應用獲得根Frame 信息並進行數據存儲。
protected async override void OnLaunched(LaunchActivatedEventArgs args)
{
Frame rootFrame = Window.Current.Content as Frame;
// 不要在窗口已包含內容時重復應用程序初始化,
// 只需確保窗口處於活動狀態
if (rootFrame == null)
{
// 創建要充當導航上下文的框架,並導航到第一頁
rootFrame = new Frame();
SuspensionManager.RegisterFrame(rootFrame, "appFrame");
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: 從之前掛起的應用程序加載狀態
}
// 將框架放在當前窗口中
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
// 當未還原導航堆棧時,導航到第一頁,
// 並通過將所需信息作為導航參數傳入來配置
if (!rootFrame.Navigate(typeof(Mainpage)))
{
throw new Exception("Failed to create initial page");
}
}
// 確保當前窗口處於活動狀態
Window.Current.Content = rootFrame;
Window.Current.Activate();
}
注意:紅色代碼處是給當前的Frame注冊掛起事件,這里只是給一個頁面的Frame注冊事件,我們可以給多個頁面注冊
2) 在OnSuspending 方法中,使用SuspensionManager.SaveAsync 方法將掛起應用的當前狀態進行保存,這里可以調用異步操作來進行處理。
/// <summary>
/// 在將要掛起應用程序執行時調用。在不知道應用程序
/// 將被終止還是恢復的情況下保存應用程序狀態,
/// 並讓內存內容保持不變。
/// </summary>
/// <param name="sender">掛起的請求的源。</param>
/// <param name="e">有關掛起的請求的詳細信息。</param>
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
//App.xaml.cs 文件包含 Application.Suspending 事件的處理程序。Windows 即將掛起應用時會調用此事件處理程序。
//這是我們保存應用狀態以防該應用被終止的時機。我們使用 SuspensionManager 類來簡化會話狀態保存過程。
//該類會保存應用的導航狀態並為你提供保存活動頁面會話狀態的機會。
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: 保存應用程序狀態並停止任何后台活動
await SuspensionManager.SaveAsync(); //調用 SaveAsync 可保存 Frame 的導航狀態,
//然后為 Page 提供保存其內容的機會。
deferral.Complete();
}
注意:當用戶掛起應用時,程序會進入此方法里, 然后運行上面紅色的代碼,接下來會進入系統處理掛起操作,緊接着會調用頁面中的SaveState方法,處理需要保存的數據。
3)打開MainPage.xaml.cs ,添加SaveState方法,添加如下代碼,作用是用與掛起時能將當前的用戶名字段保存起來。
protected override void SaveState(Dictionary<String, Object> pageState)
{
pageState["show"] = this.show.Text;
}
到此,以上就是將會話層的數據在應用掛起時,將數據保存起來,這里只是保存簡單的string類型數據,如果需要保存更為復雜的類型,這里還需要進一步修改,請參見下一篇文章。
2.恢復操作
1)掛起操作完成后,就要進行恢復操作,將暫存的數據恢復到應用中。再次打開App.xaml.cs 在OnLaunched 方法中的PreviousExecutionState 判斷為Terminated 時加入SuspensionManager.RestoreAsync 方法恢復以前的應用狀態。
protected async override void OnLaunched(LaunchActivatedEventArgs args)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new Frame();
SuspensionManager.RegisterFrame(rootFrame, "appFrame");
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: 從之前掛起的應用程序加載狀態
SuspensionManager.RestoreAsync();
}
// 將框架放在當前窗口中
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
if (!rootFrame.Navigate(typeof(Mainpage)))
{
throw new Exception("Failed to create initial page");
}
}
// 確保當前窗口處於活動狀態
Window.Current.Content = rootFrame;
Window.Current.Activate();
}
2)在MainPage.xaml.cs 中添加LoadState方法,代碼如下所示:
/// <summary>
/// 使用在導航過程中傳遞的內容填充頁。在從以前的會話
/// 重新創建頁時,也會提供任何已保存狀態。
/// </summary>
/// <param name="navigationParameter">最初請求此頁時傳遞給
/// <see cref="Frame.Navigate(Type, Object)"/> 的參數值。
/// </param>
/// <param name="pageState">此頁在以前會話期間保留的狀態
/// 字典。首次訪問頁面時為 null。</param>
protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
if (pageState!= null&&pageState.ContainsKey("show"))
{
this.show.Text = pageState["show"].ToString();
}
}
這里需要注意的是,如果頁面MainPage.xaml.cs 中有OnNavigatedTo方法,並且你重寫了此方法,你需要自己在將LoadState引用進來,不然會出錯誤。因為如果沒有重寫OnNavigatedTo方法,系統會調用MainPage父類的OnNavigatedTo方法,在此方法中會引用LoadState方法。或者添加如下代碼頁可以。
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
}
另外在App.xaml.cs文件中:
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
this.Resuming += OnResuming;
}
紅色代碼處是添加恢復時的事件,當我們從掛起變成恢復時,會首先進入OnResuming事件中,在此事件中可以進行處理保存的數據,然后在傳入的頁面中。