[MetroApp1] Tổng quan về ứng dụng phong cách Metro

[MetroApp2] Tạo ứng dụng theo phong cách Metro sử dụng JavaScript và HTML

Trong Windows 8 Release Preview, bạn có thể khởi động vài ứng dụng và lựa chọn giữa chúng mà không phải lo lắng gì về việc làm chậm hệ thống hay làm tốn pin. Đó là bởi vì hệ thống tự động tạm hoãn (và đôi khi chấm dứt) ứng dụng đang chạy trên nền. Một ứng dụng được thiết kế tốt có thể bị tạm hoãn, chấm dứt, và bắt đầu lại bởi hệ thống, mặc dù có vẻ như nó vẫn được chạy toàn bộ thời gian.

Chúng ta sẽ tìm hiểu làm thế nào để:

  • Lưu trạng thái sử dụng các loại local storage khác nhau
  • Phục hồi trạng thái khi ứng dụng khởi động lần tiếp theo

Trước khi bắt đầu….

  • Đây là phần hướng dẫn thứ 2 trong seri hướng dẫn tạo ứng dụng Metro sử dụng JavaScript và HTML, phần 1 là Tạo ứng dụng theo phong cách Metro sử dụng JavaScript và HTML
  • Để hoàn thành hướng dẫn này, bạn cần Windows 8 và Microsoft Visual Studio Express 2012 RC dành cho Windows 8.
  • Bạn cũng cần tới giấy phép nhà phát triển (developer license).

Giới thiệu về vòng đời của ứng dụng

Trong hướng dẫn trước, chúng tôi đã mô tả cách các tập tin default.js chứa mã để xử lý kích hoạt ứng dụng. Trước khi chúng tôi quay trở lại code, chúng ta hãy nói một chút về vòng đời của ứng dụng.

Tại bất kỳ điểm nào, một ứng dụng có thể là không chạy, chạy, hoặc bị tạm hoãn.

Một ứng dụng có thể bị tạm hoãn khi người dùng chuyển sang ứng dụng khác hoặc là khi Windows rơi vào trạng thái năng lượng yếu. Trong khi ứng dụng của bạn bị tạm hoãn, nó vẫn tiếp tục cư trú trong bộ nhớ để cho người dùng có thể nhanh chóng và yên tâm chuyển đổi giữa các ứng dụng bị tạm ngưng, hay khôi phục chúng. Khi ứng dụng của bạn bị tạm hoãn rồi sau đó được khôi phục lại, bạn không phải viết bất kỳ đoạn code nào thêm để làm cho nó trông như thể nó vẫn đang chạy từ trước tới giờ.

Tuy nhiên, Windows cũng có thể chấm dứt một ứng dụng bị tạm hoãn bất cứ lúc nào để giải phóng bộ nhớ cho các ứng dụng khác hoặc để tiết kiệm điện. Khi ứng dụng của bạn bị chấm dứt, nó dừng lại và được dỡ tải (unload) khỏi bộ nhớ.

Windows thông báo cho ứng dụng của bạn khi nó bị tạm hoãn, nhưng không cung cấp thêm thông báo nào khi nó chấm dứt các ứng dụng. Điều đó có nghĩa là ứng dụng của bạn phải xử lý trường hợp bị tạm hoãn và sử dụng nó để lưu trạng thái của ứng dụng, giải phóng các nguồn tài nguyên độc quyền, xử lý ngay lập tức các file.

Để tạo ra trải nghiệm tuyệt vời cho người dùng, chúng tôi muốn ứng dụng giống như kiểu nó không bao giờ ngừng hoạt động. Điều đó có nghĩa là ứng dụng cần phải giữ lại bất kỳ dữ liệu nào mà người dùng nhập vào, cài đặt hay thay đổi, và những điều tương tự. Điều đó có nghĩa là chúng ta cần phải lưu trạng thái của ứng dụng khi chúng tôi đình chỉ ứng dụng, hay khi Windows chấm dứt nó, nhờ vậy mà sau này chúng ta có thể khôi phục lại trạng thái của nó.

Những trạng thái nào chúng ta cần lưu lại? Ngay bây giờ, điều duy nhất người dùng có thể thay đổi là nhập tên của họ. Người sử dụng cũng có thể nhấp vào nói “Xin chào” để hiển thị ra một lời chào.

Có hai loại dữ liệu cần quản lý trong ứng dụng của bạn: dữ liệu người dùng (user data) và dữ liệu phiên (session data). Trong các bước tiếp theo, chúng ta sẽ tìm hiểu làm thế nào để lưu các loại dữ liệu này.

Bước 1. Lưu dữ liệu người dùng (user data)

Dữ liệu người dùng tồn tại qua các phiên làm việc và người dùng thường xuyên truy cập nó. Trong ứng dụng của chúng tôi, giá trị của ô nhập nameInput là dữ liệu người dùng. Dữ liệu người dùng thường được lưu trữ xuyên suốt vòng đời của ứng dụng (life app). Bởi vì ứng dụng của bạn chỉ co 5 giây để chạy code khi xử lý sự kiện tạm ngưng, bạn cần chắc chắn rằng những ứng dụng quan trọng của bạn sẽ được lưu trữ trong bộ nhớ khi ứng dụng bị tạm ngưng (hoặc chấm dứt)

Windows cung cấp đối tượng Windows.Storage.ApplicationData để giúp chúng ta quản lý dữ liệu của ứng dụng. Đối tượng này có thuộc tính LocalSettings nó trả về một ApplicationDataContainer. Chúng ta có thể sử dụng ApplicationDataContainer để lưu trữ dữ liệu người dùng tồn tại xuyên suốt các phiên làm việc (sessions). Hãy lưu trữ tên người dùng đã nhập trong ApplicationDataContainer.

Để lưu dữ liệu người dùng

  • Trong file default.js, tạo ra event handler (xử lý sự kiện) cho sự kiện change của nameInput. Tên của event handler đó là nameInputChanged. Thêm đoạn code này vào ngay sau phần button1ClickHandler mà chúng ta đã tạo ra ở bài hôm trước.

[sourcecode language=”javascript”]
function nameInputChanged(eventInfo) {

}
[/sourcecode]

  • Sử dụng thuộc tính srcElement của đối tượng eventInfo để truy cập vào control nameInput.

[sourcecode language=”javascript”]
function nameInputChanged(eventInfo) {
var nameInput = eventInfo.srcElement;

}
[/sourcecode]

Bây giờ, chúng ta có thể lưu trữ tên người dùng bằng cách sử dụng bất kỳ phím nào chúng ta muốn. Hãy lưu trữ tên người sử dụng như là “userName”.

 

 

[sourcecode language=”javascript”]
function nameInputChanged(eventInfo) {
var nameInput = eventInfo.srcElement;

// Store the user’s name for multiple sessions.
var appData = Windows.Storage.ApplicationData.current;
var localSettings = appData.localSettings;
localSettings.values["userName"] = nameInput.value;
}
[/sourcecode]


 

  • Trong phần 1: tạo ứng dụng “Hello, world”, chúng ta đã sử dụng onactivated event handler để đăng ký xử lý sự kiện helloButton. Bây giờ, hãy viết thêm code để đăng ký nameInputChanged event handler với control nameInput.

 

[sourcecode language=”javascript”]
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());

// 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);

}
};
[/sourcecode]

Bây giờ, khi bạn chạy ứng dụng, tên của bạn sẽ được lưu trữ khi bạn nhập vào textbox. Nhưng khi ứng dụng của bạn khởi động lại, tên của bạn không xuất hiện nữa. Bởi vậy, chúng ta cần viết thêm code để tải trạng thái (state) mà chúng ta đã lưu trữ ở bước thứ 3. Trước khi chúng ta làm điều đó, hãy tìm hiểu làm thế nào để chúng ta lưu dữ liệu phiên làm việc (session data).

Bước 2: Lưu trữ dữ liệu phiên làm việc (session data)

Sesion data là dữ liệu tạm thời nó liên quan tới phiên làm việc hiện tại của người dùng trong ứng dụng của bạn. Một phiên làm việc kết thúc khi người dùng đóng ứng dụng bằng Task Manager, hay khởi động lại máy tính, logs off máy tính, hay sử dụng phím Alt + F4 để đóng ứng dụng, etc. Trong ứng dụng của bạn, innerText của div greetingOutput là session data. Chúng ta chỉ khôi phục nó khi Windows tạm hoãn hoặc chấm dứt ứng dụng. Để lưu trữ session data, sử dụng đối tượng WinJS.Application.sessionState.

Khi nào chúng ta cần lưu trữ session data? File default.js chứa oncheckpoint event handler mà chúng ta có thể sử dụng. Event handler này được gọi khi Windows tạm ngưng ứng dụng.

Để lưu trữ session data

Trong default.js, đi tới phần oncheckpoint event handler.

Bởi vì lời chào chỉ được lưu trữ ở session, chúng tôi lưu nó trong đối tượng WinJS.Application.sessionState. Để sử dụng đối tượng sessionState, chúng ta cần thêm thuộc tính cho nó và gán giá trị cho thuộc tính ấy. Hãy gọi thuộc tính greetingOutput.

[sourcecode language=”javascript”]
app.oncheckpoint = function (args) {
// TODO: This application is about to be suspended. Save any state
// that needs to persist across suspensions here. You might use the
// WinJS.Application.sessionState object, which is automatically
// saved and restored across suspension. If you need to complete an
// asynchronous operation before your app is suspended, call
// args.setPromise().

// Store the greeting output for this session
var greetingOutput = document.getElementById("greetingOutput");
WinJS.Application.sessionState.greetingOutput = greetingOutput.innerText;
};
[/sourcecode]

Đây là tất cả những gì chúng ta cần làm để lưu trạng thái của ứng dụng khi nó bị kết thúc. Bây giờ là lúc chúng ta học cách để khôi phục trạng thái ở lần khởi động tiếp theo của ứng dụng.

Bước 3: Khôi phục trạng thái của ứng dụng

Chúng ta hãy nhìn lại một cách cẩn thẩn trong phần xử lý sự kiện onactivated nó xử lý việc kích hoạt ứng dụng.

Điều đầu tiên, khai báo biến app chứa tham chiếu tới ứng dụng. Sau đó tạo ra biến activation nó tham chiếu tới Windows.ApplicationModel.Activation namespace. Sau đó gọi hàm WinJS.strictProcessing.

[sourcecode language=”javascript”]
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
WinJS.strictProcessing();
[/sourcecode]

Tiếp theo, viết code để định nghĩa activated event handler.

[sourcecode language=”javascript”]
app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
[/sourcecode]

Tiếp theo, xử lý kiểm tra trạng thái của lần thực hiện trước để thấy xem làm thế nào ứng dụng shutdown

[sourcecode language=”javascript”]
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.
}

[/sourcecode]

Cuối cùng, xử lý gọi metho WinJS.UI.processAll và code thêm phần đăng ký event handlers. Nó gọi đoạn code này mỗi khi ứng dụng khởi động, liên quan tới trạng thái lần thực hiện trước của ứng dụng.

[sourcecode language=”javascript”]

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());

// 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);

}
};
[/sourcecode]

Giờ đây chúng ta đã hiểu những gì mà xử lsy sự kiện onactivated làm, hay sử dụng nó để lưu trữ trạng thái ứng dụng.

Để lưu trạng thái của ứng dụng

  • Tải lời chào khi previousExecutionStateterminated
  • Trong mệnh đề else, kiểm tra xem WinJS.Application.sessionState.greetingOutput có giá trị hay chưa?

[sourcecode language=”javascript”]
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) {

}
}
args.setPromise(WinJS.UI.processAll());

// 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);

}
};
[/sourcecode]

  • Nếu WinJS.Application.sessionState.greetingOutput chưa có giá trị, hãy gọi phần tử div greetingOutput div và dùng nó để hiển thị lời chào.

[sourcecode language=”javascript”]
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());

// 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);

}
};
[/sourcecode]

 

  • Bây giờ chúng ta sẽ tải user name. Bởi vì chúng ta muốn dữ liệu user name tồn tại thông qua nhiều sessions, nên chúng ta đã lưu trữ nó trong localSettings của ứng dụng. Hãy thêm một vài đoạn mã để lấy ra app data container và hiển thị user name, nếu nó tồn tại.

 

[sourcecode language=”javascript”]
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());

// 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 the user name.
var localSettings = Windows.Storage.ApplicationData.current.localSettings;
var userName = localSettings.values["userName"];
if (userName) {
nameInput.value = userName;
}

}
};
[/sourcecode]

Bây giờ hãy build và chạy ứng dụng, bạn thấy cách nó lưu trữ và khôi phục session state. Hơn thế, bạn có thể kiểm tra bằng cách chạy in chế độ debug, và dừng lại nó bằng cách lựa chọn Stop Debugging trong Microsoft Visual Studio. Nhưng đây là cách shutdown bình thường, và sự kiện Suspending không xảy ra. May mắn thay, Visual Studio cho phép bạn giả lập suspending(tạm ngưng), terminating(kết thúc) và restoring(khôi phục) một ứng dụng.

Để giả lập sự kiện suspending, terminating, restoring ứng dụng trong Visual Studio

 

  • Nhấn F5 để chạy ứng dụng trong chế độ debug
  • Nhập tên của bạn vào input box và click “:Say Hello”. Lời chào được hiển thị.
  • Nhấn Alt + Tab để trở lại Visual Studio
  • Mở drop down menu, click Suspend button trên Debug toolbar.

    Thanh công cụ Debug được hiển thị mặc định đang chạy chế độ debugger. Nếu bạn không thấy thì vào View > Toolbars > Debug để hiển thị nó.

  • Chọn Suspend and shutdown.

 

Visual Studio simulates tạm ngưng và chấm dứt ứng dụng của bạn, do đó sự kiện Suspending xảy ra và code duy trì trạng thái của bạn được thực hiện.

Tổng kết

Chúc mừng bạn đã hoàn thành hướng dẫn. Bạn đã biết cách quản lý vòng đời của ứng dụng và lưu trữ trạng thái.

Phần tiếp theo

Trong phần tiếp theo của loạt ví dụ này, bạn sẽ học cách tạo ra ứng dụng phức tạp hơn. Phần 3: Tạo ra blog reader.

Tham khảo

http://msdn.microsoft.com/en-us/library/windows/apps/hh986966.aspx