第二部分:管理應用程式週期與狀態 (HTML)

Applies to Windows only

您可以啟動數個應用程式並在它們之間切換,而不用擔心拖慢系統或耗用電池電量。 這是因為系統會自動暫停 (有時候會終止) 在背景執行的應用程式。藉由在應用程式暫停或終止時儲存它的狀態,並在應用程式重新啟動時還原狀態,您可以讓應用程式看起來像是不曾停止執行。

了解如何:

  • 使用不同類型的漫遊儲存裝置來儲存狀態
  • 在應用程式下次啟動時還原應用程式狀態

提示  

如果您想要略過教學課程並直接跳到程式碼,請參閱 JavaScript 入門:教學課程系列的完整程式碼

開始之前...

關於應用程式週期

上個教學課程中,我們說明 default.js 檔案如何包含處理應用程式啟用的程式碼。回到程式碼之前,先來談談應用程式週期。

在任何特定時間點,應用程式都處於沒有執行、正在執行或暫停的狀態。

應用程式週期

當使用者跳出某個應用程式,或當裝置進入電源不足狀態時,應用程式就會暫停。 應用程式暫停時,它會繼續停留在記憶體中,這樣使用者就可以快速並穩定地在暫停的應用程式之間切換並繼續。 當您的應用程式暫停並繼續的時候,您不需要撰寫任何額外的程式碼,讓它看起來好像一直處於執行狀態。

作業系統也可以隨時終止暫停的應用程式,以便釋出記憶體給其他應用程式或節省電源。當您的應用程式終止後,它會停止執行並從記憶體卸載。

當使用者按 Alt+F4 或使用關閉手勢關閉應用程式時,應用程式會暫停 10 秒鐘後再終止。

作業系統暫停應用程式時會通知您,但是終止應用程式則不會提供另外的通知。 這表示您的應用程式必須處理暫停事件來儲存狀態,並立即釋放它的專用資源和檔案控制代碼。

為了建立良好的使用者體驗,我們會希望應用程式看起來就像沒有停止過一樣。這表示應用程式需要保留使用者輸入的任何資料、變更的設定等等。這表示我們需要在暫停應用程式時儲存應用程式的狀態,以便在作業系統終止應用程式之後還原狀態。

您可以在應用程式管理兩種資料類型:「應用程式資料」和「工作階段資料」

在下個步驟中,我們會學習如何更新應用程式以儲存這些資料類型。我們需要儲存哪些狀態?現在,使用者唯一可以變更的是他們的名稱項目。使用者也可以按一下 Say "Hello" 按鈕產生個人化的問候語。

步驟 1。儲存應用程式資料

每個工作階段都要有應用程式資料,而且必須能夠讓使用者隨時存取。在我們的應用程式中,nameInput input 方塊的 value 是應用程式資料—亦即使用者執行應用程式時應顯示在應用程式中的設定。 因為您的應用程式最多只有五秒鐘的時間可以執行暫停事件處理常式中的程式碼,所以在應用程式暫停 (或終止) 之前必須確保重要的應用程式資料已經儲存到永續性儲存體。最好的方法是在資料變更時以增量方式儲存應用程式資料。

我們可以使用 Windows.Storage.ApplicationData 物件,協助我們管理應用程式資料。 這個物件有可以傳回 ApplicationDataContainerroamingSettings 屬性。我們可以使用這個漫遊 ApplicationDataContainer 來儲存跨多個工作階段持續存在的使用者資料。讓我們在使用者輸入他們的名稱時將使用者名稱與評分儲存在漫遊 ApplicationDataContainer中。

附註  本教學課程說明如何使用 roamingSettings。漫遊設定應用程式資料容器讓儲存資料變得更簡單,使用者可以透過多部電腦存取這些資料。基本上,資料會在背景上傳到雲端。您也可以使用本機設定應用程式資料容器 (localSettings),但您應只在想儲存電腦特定的資訊時才使用它。

我們使用第一部分:建立 "Hello, world!" 應用程式中的程式碼開始。

Hh986966.wedge(zh-tw,WIN.10).gif儲存應用程式資料

  1. 在 default.js 檔案中,為 nameInput input 方塊的 change 事件建立事件處理常式。將事件處理常式命名為 nameInputChanged。 將這個程式碼放在我們在第一部分建立的 buttonClickHandler 後面。

    
        function nameInputChanged(eventInfo) {
    
        }
    
    
  2. 使用 eventInfo 物件的 srcElement 屬性來存取 nameInput 控制項。(srcElement 屬性會抓取觸發事件的元素)。

    
        function nameInputChanged(eventInfo) {
            var nameInput = eventInfo.srcElement;
    
        }
    
    
  3. 將使用者名稱儲存在漫遊設定的 ApplicationDataContainer

    1. 呼叫 Windows.Storage.ApplicationData.current 屬性來取得應用程式的 ApplicationData 物件。
    2. 接著呼叫 ApplicationData 物件的 roamingSettings 屬性來取得漫遊設定的 ApplicationDataContainer

    現在我們可以使用任何想要的機碼來儲存使用者名稱。我們將使用者名稱儲存為 "userName"。

    
        function nameInputChanged(eventInfo) {
            var nameInput = eventInfo.srcElement;
    
            // Store the user's name for multiple sessions.
            var appData = Windows.Storage.ApplicationData.current;
            var roamingSettings = appData.roamingSettings;
            roamingSettings.values["userName"] = nameInput.value;
        }
    
    
  4. 第一部分:建立 "Hello, world" 應用程式中,我們使用 onactivated 事件處理常式來登錄我們的事件處理常式。 現在,我們再多新增一些程式碼,來登錄 nameInputChanged 事件處理常式與 nameInput 控制項。

    
        app.onactivated = function (args) {
            if (args.detail.kind === activation.ActivationKind.launch) {
                if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                    // TODO: This application has been newly launched. Initialize
                    // your application here.
                } else {
                    // TODO: This application has been reactivated from suspension.
                    // Restore application state here.
                }
                args.setPromise(WinJS.UI.processAll().then(function completed() {
                    
                    // Retrieve the button and register our event handler. 
                    var helloButton = document.getElementById("helloButton");
                    helloButton.addEventListener("click", buttonClickHandler, false);
    
                    // Retrieve the input element and register our
                    // event handler.
                    var nameInput = document.getElementById("nameInput");
                    nameInput.addEventListener("change", nameInputChanged);
    
                }));
    
            }
        };
    
    
  5. 現在,我們來儲存評分控制項變更時的狀態。我們只需要更新在第一部分中建立的事件處理常式,便可將值儲存到我們的 roamingSettings 應用程式容器。將評分儲存為 greetingRating

    
        function ratingChanged(eventInfo) {
    
            var ratingOutput = document.getElementById("ratingOutput");
            ratingOutput.innerText = eventInfo.detail.tentativeRating;
    
            // Store the rating for multiple sessions.
            var appData = Windows.Storage.ApplicationData.current;
            var roamingSettings = appData.roamingSettings;
            roamingSettings.values["greetingRating"] = eventInfo.detail.tentativeRating;
        }
    
    

現在,當您執行應用程式的時候,在文字方塊中輸入名稱與評分,就可以馬上儲存。不過,重新啟動應用程式時,您的名稱不會重新出現。這是因為我們需要新增程式碼,來載入剛剛儲存的狀態。我們會在步驟 3 中執行這個動作。但是進行之前,我們先來了解如何儲存工作階段資料。

步驟 2:儲存工作階段資料

工作階段資料是與應用程式中使用者目前工作階段相關的暫時資料。當使用者使用關閉手勢或 Alt + F4 關閉應用程式、重新啟動電腦或是登出電腦時,工作階段便會結束。 在我們的應用程式中,greetingOutput divinnerText 就是工作階段資料。只有在 Windows 暫停和終止應用程式時,我們才會還原這個資料。若要儲存工作階段資料,請使用 WinJS.Application.sessionState 物件。

何時會儲存工作階段資料?我們的 default.js 檔案包含可使用的 oncheckpoint 事件處理常式。當 Windows 即將暫停我們的應用程式時,會呼叫這個事件處理常式。不過,最好以增量方式儲存變更的工作階段資料,就像我們對應用程式資料的處理方式一樣,因此,每當使用者按一下 "Say Hello" 按鈕時,我們就會儲存工作階段資料。

Hh986966.wedge(zh-tw,WIN.10).gif儲存工作階段資料

  • 在 default.js 中,更新您在第一部分:建立 "Hello, world!" 應用程式中建立的 buttonClickHandler 函式,讓它儲存個人化問候語。

    因為只需要針對工作階段儲存此個人化問候語,所以我們將它儲存在 WinJS.Application.sessionState 物件中。若要使用 sessionState 物件,我們只要新增一個屬性,並設定該屬性的值就可以了。 我們把這個屬性稱為 greetingOutput

    
        function buttonClickHandler(eventInfo) {
    
            var userName = document.getElementById("nameInput").value;
            var greetingString = "Hello, " + userName + "!";
            document.getElementById("greetingOutput").innerText = greetingString;
    
            // Save the session data. 
            WinJS.Application.sessionState.greetingOutput = greetingString;
        }
    
    

我們只需要執行這個動作,就可以在應用程式終止之前儲存應用程式狀態。現在,我們需要學習如何在使用者下次啟動應用程式時還原應用程式狀態。

步驟 3:還原應用程式狀態

我們來看看處理應用程式啟用的 onactivated 事件處理常式程式碼。

程式碼做的第一件事是取得應用程式的參考,並將它儲存在名為 app 的變數中。 接著,它會建立名為 activation 的變數,這個變數會參考 Windows.ApplicationModel.Activation 命名空間。這兩個步驟完全是選擇性的,只是用來減少參考應用程式或 Windows.ApplicationModel.Activation 命名空間時的打字量。


    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;


接下來,程式碼會定義啟用事件處理常式。 這個處理常式會檢查剛才發生的啟用類型。只能在啟用為 launch 啟用時才能運作。如果發生的是另一種啟用類型,處理常式不會執行任何動作。

(您可以延伸事件處理常式來回應其他啟用類型,但是本教學課程沒有涵蓋這個內容。如需詳細資訊,請參閱應用程式週期)。



    app.onactivated = function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
          

接下來,處理常式會檢查之前的執行狀態,查看應用程式上次是如何關機的。



            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }


當之前的執行狀態是 terminated,表示上次應用程式執行時,Windows 成功地暫停應用程式並予以終止。如果應用程式沒有被終止,處理常式會將它視為第一次啟動。

最後,處理常式會呼叫 WinJS.UI.processAll 方法,以及我們新增來登錄事件處理常式的程式碼。無論之前的執行狀態為何,每次應用程式啟動時都會呼叫這個程式碼。



            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }
            args.setPromise(WinJS.UI.processAll().then(function completed() {

                // Retrieve the div that hosts the Rating control.
                var ratingControlDiv = document.getElementById("ratingControlDiv");

                // Retrieve the actual Rating control.
                var ratingControl = ratingControlDiv.winControl;

                // Register the event handler. 
                ratingControl.addEventListener("change", ratingChanged, false);

                // Retrieve the button and register our event handler. 
                var helloButton = document.getElementById("helloButton");
                helloButton.addEventListener("click", buttonClickHandler, false);

                // Retrieve the input element and register our
                // event handler.
                var nameInput = document.getElementById("nameInput");
                nameInput.addEventListener("change", nameInputChanged);

            }));

        }
    };

我們現在了解 onactivated 事件處理的功用,可以開始用它來還原應用程式狀態了。

Hh986966.wedge(zh-tw,WIN.10).gif還原應用程式狀態

  1. previousExecutionStateterminated 的時候,請載入我們的個人化問候語。

    在註解說明要還原應用程式狀態的 else 子句中,查看 WinJS.Application.sessionState.greetingOutput 是否已設定值。 如果沒有值的話,請抓取 greetingOutput div 元素,並用它來顯示問候語。

    
        app.onactivated = function (args) {
            if (args.detail.kind === activation.ActivationKind.launch) {
                if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                    // TODO: This application has been newly launched. Initialize
                    // your application here.
                } else {
                    // TODO: This application has been reactivated from suspension.
                    // Restore application state here.
    
                    // Retrieve our greetingOutput session state info, 
                    // if it exists. 
                    var outputValue = WinJS.Application.sessionState.greetingOutput;
                    if (outputValue) {
                        var greetingOutput = document.getElementById("greetingOutput");
                        greetingOutput.innerText = outputValue;
                    }
                }
                args.setPromise(WinJS.UI.processAll().then(function completed() {
    
                    // Retrieve the div that hosts the Rating control.
                    var ratingControlDiv = document.getElementById("ratingControlDiv");
    
                    // Retrieve the actual Rating control.
                    var ratingControl = ratingControlDiv.winControl;
    
                    // Register the event handler. 
                    ratingControl.addEventListener("change", ratingChanged, false);
    
                    // Retrieve the button and register our event handler. 
                    var helloButton = document.getElementById("helloButton");
                    helloButton.addEventListener("click", buttonClickHandler, false);
    
                    // Retrieve the input element and register our
                    // event handler.
                    var nameInput = document.getElementById("nameInput");
                    nameInput.addEventListener("change", nameInputChanged);
    
                }));
    
            }
        };
    
    
  2. 現在我們載入使用者名稱與評分。 因為我們希望使用者名稱與評分資料在多個工作階段持續存在,所以將它儲存在 roamingSettings 應用程式資料容器中。我們新增一些程式碼來擷取應用程式資料容器並顯示使用者名稱與評分 (如果有的話)。

    無論應用程式上次執行時以何種方式關閉,我們都希望執行此程式碼 (我們只需檢查工作階段資料的上次執行狀態),因此,我們將它新增到會檢查應用程式上次執行狀態的 if 子句之外。將它新增到 WinJS.UI.processAllthen 處理常式內,即登錄事件的位置。

    
        app.onactivated = function (args) {
            if (args.detail.kind === activation.ActivationKind.launch) {
                if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                    // TODO: This application has been newly launched. Initialize
                    // your application here.
                } else {
                    // TODO: This application has been reactivated from suspension.
                    // Restore application state here.
    
                    // Retrieve our greetingOutput session state info, 
                    // if it exists. 
                    var outputValue = WinJS.Application.sessionState.greetingOutput;
                    if (outputValue) {
                        var greetingOutput = document.getElementById("greetingOutput");
                        greetingOutput.innerText = outputValue;
                    }
                }
                args.setPromise(WinJS.UI.processAll().then(function completed() {
    
                    // Retrieve the div that hosts the Rating control.
                    var ratingControlDiv = document.getElementById("ratingControlDiv");
    
                    // Retrieve the actual Rating control.
                    var ratingControl = ratingControlDiv.winControl;
    
                    // Register the event handler. 
                    ratingControl.addEventListener("change", ratingChanged, false);
    
                    // Retrieve the button and register our event handler. 
                    var helloButton = document.getElementById("helloButton");
                    helloButton.addEventListener("click", buttonClickHandler, false);
    
                    // Retrieve the input element and register our
                    // event handler.
                    var nameInput = document.getElementById("nameInput");
                    nameInput.addEventListener("change", nameInputChanged);
    
                    // Restore app data. 
                    var roamingSettings = Windows.Storage.ApplicationData.current.roamingSettings;
    
                    // Restore the user name.
                    var userName =
                        Windows.Storage.ApplicationData.current.roamingSettings.values["userName"];
                    if (userName) {
                        nameInput.value = userName;
                    }
    
                    // Restore the rating. 
                    var greetingRating = roamingSettings.values["greetingRating"];
                    if (greetingRating) {
                        ratingControl.userRating = greetingRating;
                        var ratingOutput = document.getElementById("ratingOutput");
                        ratingOutput.innerText = greetingRating;
                    }
    
                }));
    
            }
        };
    
    

現在,您可以建置和執行應用程式,並查看它如何儲存和還原工作階段狀態。到目前為止,您已經在偵錯模式執行應用程式並進行測試,並在 Microsoft Visual Studio 中選取 [停止偵錯] 來停止它。不過執行這個動作會讓應用程式執行正常關機,而且不會發生 Suspending 事件。所幸,Visual Studio 能夠讓您模擬暫停、終止以及還原應用程式。

Hh986966.wedge(zh-tw,WIN.10).gif在 Visual Studio 中模擬暫停、終止以及還原應用程式

  1. 按 F5 在偵錯模式中執行應用程式。
  2. 在輸入方塊中輸入您的名稱並按一下 "Say "Hello""。此時會顯示問候語。
  3. 按 Alt+Tab 返回 Visual Studio。
  4. 開啟 [偵錯位置] 工具列的 [暫停] 按鈕旁邊的下拉式功能表。

    偵錯工具執行時,預設會顯示 [偵錯] 工具列。如果沒有看到這個工具列,請依序選取 [檢視] > [工具列] > [偵錯位置] 來顯示它。

    暫止並關閉按鈕

  5. 選取 [暫止並關閉]

    Visual Studio 會模擬暫停和終止您的應用程式,因此會發生 Suspending 事件並執行您的狀態管理程式碼。

  6. 按 F5 重新執行應用程式。應用程式會還原為之前的狀態。

摘要

恭喜,您完成這個教學課程了!您已經學會如何管理應用程式週期及儲存狀態。本教學課程只示範了儲存應用程式狀態的其中兩種方法。若要深入了解儲存狀態的其他方式,請參閱管理應用程式資料有效使用狀態

下載範例

您是否遇到困難,或是想檢查您的工作?如果是,請下載 JavaScript 入門範例

後續步驟

在本教學課程系列的下一個部分,您將會學到如何建立更複雜的應用程式。請繼續第三部分:PageControl 物件與瀏覽

相關主題

JavaScript 入門:教學課程系列的完整程式碼
使用 HTML、CSS 及 JavaScript 設計 Windows 8 應用程式 (電子書)

 

 

顯示:
© 2014 Microsoft