sobota, 10 grudnia 2011

Notatki o Windows 8 - odc.9

Cykl życia aplikacji Metro (aktywacja, usypianie, terminacja, przywracanie) oraz zarządzanie jej danymi (ustawieniami i plikami lokalnymi, ustawieniami i plikami w roamingu oraz plikami tymczasowymi).

Application lifecycle

Activation

document.addEventListener("DOMContentLoaded", domcontentloadedHandler, false);

function domcontentloadedHandler()

{

    Windows.UI.WebUI.WebUIApplication.addEventListener("activated", activatedHandler, false);

}

When the user switches to your terminated app, the system sends the activated event, with the LaunchActivatedEventArgs.kind property set to launch and the LaunchActivatedEventArgs.previousExecutionState property set to terminated. The app should load its saved application data and refresh its displayed content.

function activatedHandler(eventArgs)

{

    if (eventArgs.kind == Windows.ApplicationModel.Activation.ActivationKind.launch)

    {

 

        var activatedReason = eventArgs.previousExecutionState;

        if (activatedReason == Windows.ApplicationModel.Activation.ApplicationExecutionState.terminated)

        {

 

            // TODO: Populate the UI with the previously saved application data            

 

        }

        else

        {

 

            // TODO: Populate the UI with defaults            

 

        }

    }

}

If the value of previousExecutionState is notRunning, the app failed to save its application data successfully and the app should start over as if it were being initially launched.

When the system launches your app, there may be additional context for the activation. Check the LaunchActivatedEventArgs.arguments property.

function activatedHandler(eventArgs)

{

    if (eventArgs.kind == Windows.ApplicationModel.Activation.ActivationKind.launch)

    {

        if( eventArgs.arguments !== '')

        {

            // TODO: Parse the arguments string

        }

    }

}

The format and contents of an argument string is defined by the app. When activating an app through a tile, arguments can be passed using the arguments parameter of the SecondaryTile constructor or the SecondaryTile.Arguments property. When activating an app through a toast notification, arguments can be specified through the launch attribute of the toast element.

When an app is launched, activation and loading events are fired in this order:

Note that you can't detect the activation type in the DOMContentLoaded event, so its event handler should not perform tasks related to activation, it should mostly register to handle other events and set up UI to replace the splash screen.

When a running app is activated, the system sends the activated event only.

If a page is refreshed, only the DOMContentLoaded and window.load events are raised.

Suspending

Windows.UI.WebUI.WebUIApplication.addEventListener("suspending", suspendingHandler, false);

It is a good idea to register to handle the suspending event in your event handler for the DOMContentLoaded event.

When your app handles the suspending event, it has the opportunity to save its important application data in the handler function. The app can use the settings API (Windows.Storage.ApplicationData.localSettings or Windows.Storage.ApplicationData.roamingSettings) to save simple application data synchronously.

This sample saves application data to a file on disk asynchronously. The handler calls the SuspendingOperation.getDeferral method to indicate that the app is saving its application data asynchronously. When the write operation completes, the handler calls the SuspendingDeferral.complete method to indicate that the app's application data has been saved. If the app does not call complete, the system assumes the app is not responding and terminates it.

var app = WinJS.Application;

var myfile = "myfile.text";

 

function suspendingHandler(eventArgs)

{

        // Use the getDeferral method to request asynchronous handling of the suspension

        var deferral = eventArgs.suspendingOperation.getDeferral();

 

        // Do the asynchronous work of persisting data, in the userTextValue string, to a file

        app.local.writeText(myfile, userTextValue).then(function () {

            // Call the complete method as follows or else the app is terminated.

            deferral.complete();

        });

}

Note that you can use the SuspendingOperation object provided to determine whether there's enough time to save optional application data before suspension. See the SuspendingOperation.deadline property.

The system suspends your app whenever the user switches to another app or to the desktop. The system resumes your app whenever the user switches back to it. When the system resumes your app, the content of your variables and data structures is the same as it was before the system suspended the app. The system restores the app exactly where it left off, so that it appears to the user as if it's been running in the background.

The system attempts to keep your app and its data in memory while it is suspended. However, if the system does not have the resources to keep your app in memory, the system will terminate your app. When the user switches back to a suspended app that has been terminated, the app receives an activated event with previousExecutionState set to terminated, indicating that it should restore its application data.

The system does not notify an app when it is terminated, so your app must save its application data when it is suspended so that it can be restored when the app is activated after termination.

Resuming

Windows.UI.WebUI.WebUIApplication.addEventListener("resuming", resumingHandler, false);

The app may have been suspended for a significant amount of time, so it should refresh any displayed content that might have changed while the app was suspended, such as news feeds or the user's location. If your app doesn't have any displayed content to refresh, there's no need to it to handle the resuming event.

Guidelines

Most Metro style apps should stop what they are doing when the user switches away from them. There are very few apps that should continue to run when they lose focus; for example, a music player should continue to play music even after the user has switched to another app.

Generally, resume your app as the user left it rather than starting it fresh

Start the app fresh if a long period of time has elapsed since the user last accessed it.

Provide users with options if you cannot predict whether they want to resume or start over. It might not always make sense to bring the app back to where it left off. Instead, provide the user with a set of options for what to do next. For example, when the user switches back to your game, you could display a prompt to enable the user to decide whether to resume the game or start a new one.

Do not terminate the app when it is moved off screen.

Do not restore state for an app that terminated as the result of a crash.

Do not offer users ways to terminate your app. Users should feel confident that the system is managing their apps for them. Metro style apps should not display Close buttons or other ways to exit the app. Allow your app to be terminated by the system to ensure the best system performance and reliability.

Application data

Local application data

Register for the datachanged event in the domcontentloadedHandler event handler for the DOMContentLoaded event. This example sets datachangeHandler as the handler for local data changes by other instances of the same app.

var applicationData = Windows.Storage.ApplicationData.current;

 

function domcontentloadedHandler()

{

    applicationData.addEventListener("datachanged", datachangeHandler, false);

}

 

function dataChangedHandler(eventArgs)

{

    // TODO: Refresh your data

}

var localSettings = applicationData.localSettings;

var localFolder = applicationData.localFolder;

localSettings.values["exampleSetting"] = "Hello Windows";

applicationData.signalDataChanged();

After changing a setting in the local app data store, the app must call the ApplicationData.signalDataChanged method to fire the datachanged event so that any other instances of the app on the device are notified of the change.

var composite = new Windows.Storage.ApplicationDataCompositeValue();

composite["intVal"] = 1;

composite["strVal"] = "string";

 

localSettings.values["exampleCompositeSetting"] = composite;

applicationData.signalDataChanged();

Container:

var container = localSettings.createContainer("exampleContainer", Windows.Storage.ApplicationDataCreateDisposition.Always);

 

if (localSettings.containers.hasKey("exampleContainer"))

{

    localSettings.containers.lookup("exampleContainer").values["exampleSetting"] = "Hello Windows";

    applicationData.signalDataChanged();

}

Reading data

var value = localSettings.values["exampleSetting"];

var hasContainer = localSettings.containers.hasKey("exampleContainer");

if (hasContainer)

{

    // Access data in localSettings.containers.lookup("exampleContainer").values.hasKey("exampleSetting");

}

Write data to a file

localFolder.createFileAsync("dataFile.txt", Windows.Storage.CreationCollisionOption.replaceExisting).then(function (dataFile) {

    dataFile.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {

        var outputStream = stream.getOutputStreamAt(0);

        var writer = new Windows.Storage.Streams.DataWriter(outputStream);

        var date = new Date();

        writer.writeString(date);

        writer.storeAsync().then(function () {

            outputStream.flushAsync().then(function () {

                // Display the data

            });

        });

    });

});

Read data from file

localFolder.createFileAsync("dataFile.txt", Windows.Storage.CreationCollisionOption.openIfExists).then(function (dataFile) {

    dataFile.openAsync(Windows.Storage.FileAccessMode.read).then(function (stream) {

        var size = stream.size;

        if (size == 0)

        {

            // Data not found

        }

        else

        {

            var inputStream = stream.getInputStreamAt(0);

            var reader = new Windows.Storage.Streams.DataReader(inputStream);

 

            reader.loadAsync(size).then(function() {

                var contents = reader.readString(size);

                var date = new Date(contents);

                // Data is contained in date

            });

        }

    });

});

Delete settings

localSettings.values.remove("exampleSetting");

localSettings.deleteContainer("exampleContainer");

Roaming application data

var applicationData = Windows.Storage.ApplicationData.current;

 

function domcontentloadedHandler()

{

    applicationData.addEventListener("datachanged", datachangeHandler, false);

}

var roamingSettings = applicationData.roamingSettings;

var roamingFolder = applicationData.roamingFolder;

roamingSettings.values["exampleSetting"] = "Hello World";

 

Analogicznie do lokalnych ustawień także dla złożonych i kontenerów, odczyt wszystkiego też.

Analogiczny zapis pliku:

 

roamingFolder.createFileAsync("dataFile.txt", Windows.Storage.CreationCollisionOption.replaceExisting).then(function (dataFile) {

    dataFile.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {

        var outputStream = stream.getOutputStreamAt(0);

        var writer = new Windows.Storage.Streams.DataWriter(outputStream);

        var date = new Date();

        writer.writeString(date);

        writer.storeAsync().then(function () {

            outputStream.flushAsync().then(function () {

                // Display the data

            });

        });

    });

});

 

Analogiczny odczyt z pliku i usuwanie ustawień.

 

Each app has a quota for roaming application data. Check the ApplicationData.roamingStorageQuota property to determine the total size of roaming data allowed, check the ApplicationData.roamingStorageUsage property to determine how much roaming data you've got, and subtract roamingStorageUsage from roamingStorageQuota to determine the remaining quota.

 

Roaming application data lets users keep your app's application data in sync across multiple devices like their work PC and their slate at home. If a user installs the same app on two devices, Windows keeps the app data, like user preferences, in sync. This reduces the amount of setup work that the user needs to do for your app on their second device.

 

Do use roaming for first time setup of a new app. Roam any application data that the end-user is likely to set on each device anyway, such as user preferences.

 

Do use roaming to let users continue a task across devices. Roam any application data that enables users to pick up a task right where they left off on a different device. This could include tasks like:

  • Composing a to-do list
  • Composing email

Don't use roaming to move large datasets.

 

Don't use romaing for instant syncing. Windows roams app data opportunistically and does not guarantee an instant sync. In scenarios where a user is offline or on a high latency network, roaming can be delayed significantly. Do not build a UI that needs that sync to occur instantly. This tends to mean that media applications that want to push up-to-the-second updates on a user’s position in a song should not rely on roaming application data.

 

Temporary application data

 

var applicationData = Windows.Storage.ApplicationData.current;

var temporaryFolder = applicationData.temporaryFolder;

 

Zapis i odczyt pliku analogiczny.

 

c.d.n

Brak komentarzy: