資訊
The topic you requested is included in another documentation set. For convenience, it's displayed below. Choose Switch to see the topic in its original location.

快速入門:使用 WinJS 中的處置模型

Applies to Windows and Windows Phone

了解如何使用 WinJS 中的處置模型,以可靠的方式控制使用 JavaScript 之 Windows 市集應用程式中控制項和其他物件的記憶體使用量。 處置模型可讓您建立控制項,在超出範圍時釋放記憶體。物件會成為「標記為處置」,這表示記憶體回收行程 (在背景執行以管理記憶體使用量的處理程序) 會在物件執行時摧毀該物件。

注意  您可以使用 Windows 效能記錄程式和 Windows 效能分析程式來觀察您應用程式的記憶體使用情況。如需 Windows 效能記錄程式和 Windows 效能分析程式的詳細資訊,請參閱 Windows 效能工具組技術參考

先決條件

指示

使用空白應用程式範本建立新專案

本文使用 Microsoft Visual Studio 2013 中基本的 [空白應用程式] 範本。若要建立新 [空白應用程式],請遵循下列步驟:

  1. 啟動 Microsoft Visual Studio。

  2. 在 [起始頁] 索引標籤,按一下 [新增專案]。隨即開啟 [新增專案] 對話方塊。

  3. 在 [已安裝的] 窗格中,依序展開 [範本]、[JavaScript] 和 [市集應用程式]。選取您要建立的應用程式類型 ([Windows]、[Windows Phone]、[通用])。適用於 JavaScript 的可用專案範本會顯示在對話方塊的中央窗格中。

  4. 在中央窗格中,挑選 [空白應用程式] 專案範本。

  5. 在 [名稱] 文字方塊中,輸入處置示範
  6. 按一下 [確定] 來建立專案。

將自訂控制項新增至專案

  1. 在 [方案總管] 中,用滑鼠右鍵按一下 [js] 資料夾,然後按一下 [加入]> [新增 JavaScript 檔]。在 [加入新項目] 對話方塊中,將新檔案命名為 RandomShapesControl.js,然後按一下 [加入]
  2. 開啟 default.html,然後將下列 <script> 標籤插入 <head> 標籤。
    
    <script src="/js/RandomShapesControl.js"></script>
    
    
  3. 開啟 RandomShapesControl.js (在 js 資料夾中),然後新增下列程式碼。
    
    
    (function () {
        "use strict";
    
        var svgNS = "http://www.w3.org/2000/svg";
    
        // Define a utility function for building HTML elements.
        function buildElement(type, attributes, text, namespace) {
            var newElement = namespace ?
                document.createElementNS(namespace, type) : document.createElement(type);
            for (var i in attributes) {
                if (attributes.hasOwnProperty(i)) {
                    newElement.setAttribute(i, attributes[i]);
                }
            }
            newElement.innerText = text || "";
            return newElement;
        }
    
        // Draw a randomly-colored rectangle onto the 'svg' container
        // element.
        function drawShape() {
            var newShape = buildElement("rect", {
                width: "30",
                height: "30",
                x: (Math.floor(Math.random() * 470) + 1).toString(),
                y: (Math.floor(Math.random() * 470) + 1).toString(),
                fill: getRandomColor()
            }, null, svgNS);
    
            document.getElementById('svg').appendChild(newShape);
        }
    
        // Generate a random RGB value as a string.
        function getRandomColor() {
            var color = function () { return Math.floor(Math.random() * 256) + 1; }
            var colorString = "rgb(" + color().toString() + "," + color().toString() 
                + "," + color().toString() + ")";
    
            return colorString;
        }
    
        WinJS.Namespace.define("Shapes", {
            RandomShape: WinJS.Class.define(
    
                // Define the constructor function / class definition for the
                // custom Random Shapes control. The Random Shapes control draws
                // a lot of randomly-colored SVG rectangles when a button is clicked. 
                function (element) {
    
                    // Implement a standard WinJS control 'interface' so that
                    // the winControl property returns this constructor function.
                    this._element = element;
                    this._element.winControl = this;
    
                    // Create an SVG container element for the rectangles.
                    this.svg = buildElement("svg", {
                        id: "svg",
                        width: "500",
                        height: "500"
                    }, null, svgNS);
    
                    // Create a button to raise the click event for the control.
                    this.drawMany = buildElement("button", {
                        id: "drawMany"
                    }, "Draw a bunch of shapes");
    
                    element.appendChild(this.svg);
                    element.appendChild(document.createElement("br"));
                    element.appendChild(this.drawMany);
    
                    // Add the click event handler to call drawManyShapes, which
                    // adds a lot of SVG elements to the SVG container.
                    this.drawMany.addEventListener("click", this.drawManyShapes);
    
                }, {
    
                    // Insert 1,000 randomly-colored shapes into the 'svg' container.
                    drawManyShapes: function () {
                        for (var i = 0; i < 1000; i++) {
                            drawShape();
                        }
                    }
                })
        });
    })();
    
    

新增適用於範例應用程式的 HTML 和 JavaScript

這個示範應用程式會建立自訂控制項,在使用者按一下按鈕時,產生大量的 SVG 元素 (1,000)。每個元素都具備獨特的色彩並放置於較大的 SVG 元素內,因而需要大量記憶體。

開啟 default.html,在 <body> 元素內插入下列 HTML。程式碼應該是 <body> 元素的直屬子系。這個 HTML 會建立兩個 <div> 元素:一個元素包含自訂控制項,另一個元素則包含要處置自訂控制項的按鈕。


<div>
    <h1>Custom random-shape generator control</h1><br/><br/>
    <p>Use the button below to dispose the Random Shapes control.</p>
    <button id="dispose">Dispose control</button>
</div><br/><br/>
<div id="randomShapes" data-win-control="Shapes.RandomShape"></div>

開啟 default.js 檔案 (在 js 資料夾中),並以下列程式碼取代 app.onactivated 事件處理常式。這個 JavaScript 會建立新的 RandomShapes 控制項,並將事件處理常式新增到 Dispose control 按鈕。


app.onactivated = function (args) {
    if (args.detail.kind === activation.ActivationKind.launch) {
        if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
            // TODO: This appl has been newly launched. Initialize
            // your app here.
        } else {
            // TODO: This app has been reactivated from suspension.
            // Restore app state here.
        }

        args.setPromise(WinJS.UI.processAll().done(
            function () {

                // Add an event handler to the 'Dispose control' button.
                dispose.addEventListener("click", function () {
                    var shapesContainer = document.getElementById("randomShapes");
                    var shapesControl = shapesContainer.winControl;

                    shapesContainer.innerHTML = "";
                    shapesContainer = null;
                });
            }
       ));
    }
};

如果您在 Visual Studio 2013 中使用 [效能與診斷] 工具來檢查應用程式的記憶體使用量,您會看見即使所有的 HTML 可能都因為將容器物件的 innerHTML 屬性設為空字串而被摧毀,但該應用程式仍會保留控制項的部分記憶體。記憶體仍然會分配給上述兩個元素。

實作處置模式

當您建立自訂控制項時,確定它不會在應用程式中導致記憶體流失。在 WinJS 中,當應用程式不再需要自訂控制項時,該控制項會使用處置模式來釋放記憶體。

在 WinJS 自訂控制項實作處置模式有兩項基本需求:

  • 控制項的容器必須使用階層式樣式表 (CSS) 類別 "win-disposable" 來標示。持有自訂控制項的 HTML 元素必須具備 class 屬性,並含有 "win-disposable" 的值。
  • 控制項的類別定義必須包含 dispose 成員。使用 WinJS.Class.define 函式宣告新類別時,類別的執行個體成員必須包含 dispose 函式。

若要改善此範例應用程式中 RandomShapes 控制項的記憶體使用量,請使用下列步驟,變更用以實作處置模式的程式碼。

  1. 開啟 RandomShapesControl.js (在 js 資料夾)。 在 RandomShapes 控制項的建構函式中,新增這行程式碼。
    
    WinJS.Utilities.addClass(element, "win-disposable");
    
    
  2. 此外,在 RandomShapesControl.js 中,使用下列程式碼來取代對 WinJS.Namespace.define 的呼叫。
    
    WinJS.Namespace.define("Shapes", {
        RandomShape: WinJS.Class.define(Control, {
            drawManyShapes: drawManyShapes,
            dispose: function () {
    
                // Remove the click-event handler from the button.
                this.drawMany.removeEventListener("click", this.drawManyShapes);
    
                // Dispose of all the child controls of this element.
                WinJS.Utilities.disposeSubTree(this._element);
    
                // Release memory from all of the class fields.
                this.svg = null;
                this.drawMany = null;
                this._element = null;
            }
        })
    });
    
    
  3. 在 default.js (js 資料夾) 中,使用下列程式碼來取代對 args.setPromise 的呼叫。這個程式碼會明確呼叫 RandomShape.dispose 來處置控制項。
    
    args.setPromise(WinJS.UI.processAll().done(
        function () {
            dispose.addEventListener("click", function () {
                var shapesContainer = document.getElementById("randomShapes");
                var shapesControl = shapesContainer.winControl;
                
                // Call dispose on the control.
                shapesControl.dispose();
    
                shapesContainer.innerHTML = "";
                shapesContainer = null;
            })
        }
    ));
    
    

這裡提供 RandomShapesControl.js 已更新的完整程式碼。



   (function () {
    "use strict";

    var svgNS = "http://www.w3.org/2000/svg";

    // Define an internal utility function for building HTML elements.
    function buildElement(type, attributes, text, namespace) {
        var newElement = namespace ?
            document.createElementNS(namespace, type) : document.createElement(type);
        for (var i in attributes) {
            if (attributes.hasOwnProperty(i)) {
                newElement.setAttribute(i, attributes[i]);
            }
        }
        newElement.innerText = text || "";
        return newElement;
    }

    // Draw a randomly colored rectangle onto the 'svg' container
    // element.
    function drawShape() {
        var newShape = buildElement("rect", {
            width: "30",
            height: "30",
            x: (Math.floor(Math.random() * 470) + 1).toString(),
            y: (Math.floor(Math.random() * 470) + 1).toString(),
            fill: getRandomColor()
        }, null, svgNS);

        document.getElementById('svg').appendChild(newShape);
    }

    // Generate a random RGB value as a string.
    function getRandomColor() {
        var color = function () { return Math.floor(Math.random() * 256) + 1; }
        var colorString = "rgb(" + color().toString() + "," + color().toString() 
            + "," + color().toString() + ")";

        return colorString;
    }

    WinJS.Namespace.define("Shapes", {
        RandomShape: WinJS.Class.define(

            // Define the constructor function / class definition for the
            // custom Random Shapes control. The Random Shapes control draws
            // a lot of randomly colored SVG rectangles when a button is clicked. 
            function (element) {

                // Implement a standard WinJS control 'interface' so that
                // the winControl property returns this constructor function.
                this._element = element;
                this._element.winControl = this;

                WinJS.Utilities.addClass(element, "win-disposable");

                // Create an SVG container element for the rectangles.
                this.svg = buildElement("svg", {
                    id: "svg",
                    width: "500",
                    height: "500"
                }, null, svgNS);

                // Create a button to raise the click event for the control.
                this.drawMany = buildElement("button", {
                    id: "drawMany"
                }, "Draw a bunch of shapes");

                element.appendChild(this.svg);
                element.appendChild(document.createElement("br"));
                element.appendChild(this.drawMany);

                // Add the click-event handler to call drawManyShapes, which
                // adds a lot of SVG elements to the SVG container.
                this.drawMany.addEventListener("click", this.drawManyShapes);

            }, {

                // Insert 1,000 randomly colored shapes into the 'svg' container.
                drawManyShapes: function () {
                    for (var i = 0; i < 1000; i++) {
                        drawShape();
                    }
                },

                // Release all references to internal objects.
                dispose: function () {

                    // Remove the click-event handler from the button.
                    this.drawMany.removeEventListener("click", this.drawManyShapes);

                    // Dispose of all the child controls of this element.
                    WinJS.Utilities.disposeSubTree(this._element);

                    // Release memory from all of the class fields.
                    this.svg = null;
                    this.drawMany = null;
                    this._element = null;
                }
            })
    });
})();

如果您在實作處置模式之後執行此範例,UI 行為會和先前完全相同:當您按一下 [繪製大量形狀] 時,系統會將上千個不同色彩的矩形新增到 SVG 元素。當您按一下 [處置控制項] 時,該控制項即會消失。

摘要

在這個快速入門中,您了解如何在使用 JavaScript 的 Windows 執行階段應用程式的自訂控制項中實作處置模型。這個快速入門並未涵蓋像是如何處置本身為 WinJS 控制項的子元素,或是如何使用 WinJS.Utilities.markDisposable 之類的問題。

 

 

顯示:
© 2015 Microsoft