Опубликован: 02.04.2013 | Доступ: свободный | Студентов: 1117 / 53 | Длительность: 20:18:00
Специальности: Программист
Лекция 4:

Анатомия приложения и навигация по страницам

Активация приложения

Для начала, позвольте мне поздравить вас с тем, что вы продвинулись так далеко в этой лекции, полной подробностей. В качестве награды, давайте поговорим кое о чем гораздо более осязаемом и привлекательном: о том, как активируется приложение, о последовательности действий, выполняемых при его запуске. Это может случиться множеством способов, с плитки на Начальном экране, с помощью контракта, при ассоциации с типом файлов или схемой URI. Во всех этих случаях активации вы будете писать много кода для инициализации структур данных, перезагрузки ранее сохранённого состояния и делать всё для того, чтобы предоставить пользователям хороший опыт взаимодействия с приложением.

Основы брендинга приложений: экран-заставка и другие визуальные элементы

Говоря об активации приложения, мы, на самом деле, должны сделать шаг назад, во время до того момента, когда будет загружен хост-процесс приложения, к тому моменту, когда пользователь нажал на плитку приложения на Начальном экране или когда ваше приложение было запущено каким-то другим способом. Первое, что происходит, еще до того, как загружается или исполняется код приложения, это - показ Windows экрана-заставки приложения, состоящего из изображения и фонового цвета, которые заданы в вашем манифесте.

Экран-заставка, который показывается, как минимум, на 0.75 секунды, это не просто картинка , которая показывает пользователям что-то интересное, пока приложение запускается (что лучше, чем песочные часы). Она так же занимает то пространство, где будет запущено приложение, в итоге, прямо привлекая внимание пользователя к этому месту. Это может быть область заполняющего просмотра, наложенная на другое приложение область, выводимая чудо-кнопкой Общий доступ или Поиск, или область режима прикрепленного просмотра, если приложение запускается сразу в прикрепленном режиме просмотра. В течение этого времени, запускается экземпляр хост-процесса приложения, обрабатываются и выводятся ваши HTML- страницы с CSS и загружается, обрабатывается и исполняется ваш JavaScript-код, по пути вызывая события, как мы увидим в следующем разделе. Когда готова первая страница приложения, система убирает экран-заставку.

Экран-заставка, вместе с плиткой вашего приложения, это один из весьма важных путей для брендирования вашего приложения, поэтому убедитесь в том, что ваш художник (или художники) уделили этим вопросам максимум внимания. Есть и другие графические элементы и установки в манифесте, которые так же играют роль в брендинге и в общем виде приложения в системе, как показано ниже, в таблице. Особо отметьте то, что шаблоны в Visual Studio и Blend предоставляют некоторые материалы-заполнители по умолчанию, которые совершенно непривлекательны. Поэтому дайте прямо сейчас торжественную клятву, что вы никогда не будете загружать приложения в Магазин, когда в проекте всё еще присутствуют эти материалы! (За дополнительными сведениями обратитесь к документу: "Руководство и контрольный список для экранов-заставов", (http://msdn.microsoft.com/library/windows/apps/hh465338.aspx).

Вы можете видеть, что в таблице перечислено по несколько размеров для различных изображений, заданных в манифесте для поддержки различной плотности пикселей: для масштабирования в 100%, 140%, 180%, и даже несколько для 80% (не пренебрегайте последним, он, как правило, используется для большинства настольных мониторов). И, в то время, как вы можете просто предоставить одно изображение в масштабе 100% для каждого из перечисленных элементов, практически гарантированно, что версия с увеличенным масштабом графических элементов будет выглядеть не очень хорошо. Поэтому, почему бы не сделать ваше приложение выглядящим наилучшим образом? Уделите время на то, чтобы осознанно создать каждый отдельный графический элемент.

Таблица 3.2.
Закладка манифеста Раздел Элемент Использование Размеры изображений
100% 140% 180%
Упаковка n/a Значок Изображение плитки/значка, используемое для приложения на странице описания в Магазине Windows. 50x50 70x70 90x90
Интерфейс приложения n/a Отображаемое имя пакета Появляется при просмотре Начального экрана в режиме "все приложения" , в результатах поиска, при использовании чудо-кнопки Параметры, в Магазине Windows. n/a n/a n/a
Плитка Значок Квадратное изображение плитки 150x150 (+80% масштаб 120x120) 210x210 270x270
Широкий значок Необязательное изображение для широкой плитки. Если присутствует, отображается по умолчанию, но пользователь, если захочет, может использовать вместо него квадратное изображение. 310x150 (+80% масштаб 248x120) 434x210 558x270
Мелкий значок Плитка, которая используется при уменьшенном просмотре Начального экрана, при просмотре в режиме "все приложения", в панелях чудо-кнопок Поиск и Общий доступ, если приложение поддерживает соответствующие контракты в качестве целевого. Кроме того, используется на плитке приложения, если вы выбрали опцию показа логотипа приложения в левом нижнем углу плитки вместо его названия. 30x30 (+80% масштаб 24x24) 42x42 54x54
Показывать имя Задаёт, следует ли показывать имя приложения на плитке приложения (на всех, не показывать, только на стандартном или на широком значке). Установите этот параметр в значение "Нет значков", если плитка вашего приложения включает имя приложения. n/a n/a n/a
Краткое имя Необязательное. Если задано, используется в качестве имени приложения на плитке, заменяя Отображаемое имя пакета, так как это имя может быть слишком длинным для квадратной плитки. n/a n/a n/a
Текст переднего плана Цвет текста, которым выведено имя приложения на плитке, если применимо (смотрите Показывать имя). Возможны варианты Светлый (Light) и Тёмный (Dark). Соотношение контраста между этим текстом и цветом фона должен равняться 1.5. n/a n/a n/a
Цвет фона Цвет, используемый для прозрачных областей любых изображений на плитке, кроме того, задаёт фон по умолчанию для дополнительных плиток, фон для окон уведомлений, цвет кнопок в диалоговых окнах приложения, цвет границ для тех случаев, когда приложение обеспечивает функциональность контракта средства выбора файлов или контактов, цвет заголовков в панели параметров, цвет страницы приложения в Магазине Windows. Кроме того, задаёт фоновый цвет для экрана-заставки, если он не задан отдельно. n/a n/a n/a
Уведомления Эмблема Отображается около уведомления индикатора событий для идентификации приложения на экране блокировки (редко, так как это требует объявления дополнительных возможностей) 24x24 33x33 43x43
Заставка Заставка Когда приложение запускается, это изображение выводится в центре экрана на фоне, цвет которого задаёт Цвет фона. Если нужно, изображение может использовать прозрачность. 620x300 868x420 1116x540
Цвет фона Цвет, который заполняет основную область экрана-заставки. Если не задан, вместо него будет использован Цвет фона из Интерфейса приложения n/a n/a n/a

Обратите внимание на то, что в таблице 80% масштаб указан для графических элементов, используемых в особых случаях, таких, как режим низкого DPI (обычно, когда DPI меньше 130 и разрешение ниже, чем 2560х1440) и изображения в таком масштабе следует предоставлять вместе с другими. Кроме того, обратите внимание на дополнительные графические элементы, помимо Значка (Packaging Logo) (первый элемент в таблице), которые вам понадобятся перед отправкой приложения в Магазин Windows. Подробности вы найдете в материале "Выбор изображений для вашего приложения" (http://msdn.microsoft.com/library/windows/apps/hh846296.aspx), в разделе "Рекламные изображения".

Когда вы сохраняете эти файлы, добавьте .scale-80, .scale-100, .scale-140, и .scale-180 к именам файлов перед расширениями, как, например, в имени: splashscreen.scale-140.png. Это позволит вам и в манифесте, и в других местах приложения ссылаться на изображение, используя лишь базовое имя, такое, как splashscreen.png, и Windows автоматически загрузит подходящий вариант для текущего масштаба. В противном случае она будет искать изображение без суффикса. И не нужно дополнительного кода! Это показано в упражнении HereMyAm3b, где я добавил всю необходимую для брендинга графику (с некоторым дополнительным текстом на каждом рисунке для того, чтобы показать масштаб). Для того, чтобы протестировать эти различные графические элементы, используя кнопку Изменить разрешение (Set resolution/scaling) в симуляторе - обратитесь к Рис. 2.5 во второй лекции. Вы можете выбирать различные плотности пикселей на экране размером 10,6" (1366 x 768 =100%, 1920 x 1080 =140%, и 2560 x 1440 = 180%). Кроме того, вы увидите, что 80%-й масштаб используется при других установках экрана, в том числе - на 23" и 27". Во всех случаях, установки влияют на то, какое изображение будет использовано на Начальном экране и на экране-заставке, но обратите внимание на то, что вам может понадобиться выйти и перезапустить симулятор для того, чтобы изменение масштаба возымело действие.

Кроме того, вы должны знать о том, что полноцветные изображения фотографического качества не очень хорошо поддаются качественному уменьшению (Значок (Store Logo, Эмблема магазина), Мелкий значок (Small Logo, Мелкая эмблема)). Это одна из причин того, что данные значки обычно имеют простой дизайн в стиле Магазина Windows, который, кроме того, способствует уменьшению их размеров при сжатии. Это - отличное соображение, следуя которому можно сделать размер пакета вашего приложения меньше, когда вы создаёте больше версий изображений для различных контрастов и языков. Больше об этом будет в "Макет" курса "Программная логика приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript и их взаимодействие с системой".

Совет. Вы можете заинтересоваться еще двумя ресурсами по брендингу. Это - материал "Создание фирменной символики в приложениях Магазина Windows" (http://msdn.microsoft.com/library/windows/apps/hh465418.aspx) из документации (посвящен дизайну) и пример "CSS-стилизация: брендирование вашего приложения (CSS styling: branding you app sample)" (http://code.msdn.microsoft.com/windowsapps/App-Branding-sample-9f87b7a2), который показывает CSS-вариации и динамическое изменение активной таблицы стилей.

Последовательность событий при активации

Так как хост-процесс приложения построен на тех же самых механизмах обработки и рендеринга, что и Internet Explorer, общая последовательность событий при активации более или менее похожа на последовательность, характерную для веб-приложений и наблюдаемую в браузере. На самом деле, скорее "более", чем "менее"! Когда вы запускаете приложение с помощью его плитки, вот что происходит с точки зрения Windows:

  1. Windows отображает экран-заставку, используя информацию из манифеста приложения.
  2. Windows запускает хост-процесс приложения, идентифицирует приложение для запуска.
  3. Хост-процесс приложения получает параметры стартовой страницы приложения (смотрите закладку Интерфейс приложения в редакторе манифеста), которые задают HTML-страницу для загрузки.
  4. Хост-процесс приложения загружает стартовую страницу вместе со связанной CSS-таблицей и скрипт (откладывает загрузку скрипта, если так указано в разметке). Важно, чтобы все файлы имели правильную кодировку для улучшения производительности загрузки (смотрите врезку ниже).
  5. Запускается событие document.DOMContentLoaded. Вы можете использовать его для того, чтобы произвести дальнейшую инициализацию, в особенности, связанную с DOM (используется редко).
  6. Запускается событие Windows.UI.WebUI.WebUIApplication.onactivated. Это обычно происходит, когда вы выполните все стартовые задачи, создадите экземпляр WinJS и элементов управления, инициализируете состояние и так далее.
  7. Экран-заставка скрывается, когда обработчик события activated завершится (если приложение не запросило отложенную операцию, как рассказано далее, в разделе "Задержанная активация").
  8. Запускается событие body.onload. Обычно оно не используется в приложениях для Магазина Windows, хотя оно может использоваться кодом из библиотек сторонних разработчиков.

Важной особенностью является то, что приложение снова может быть активировано по множеству различных причин, таких, как контракт или ассоциация, даже тогда, когда оно уже запущено. Как мы увидим в дальнейших лекциях, загружаемая страница (шаг 3), может варьироваться при реализации контракта, и если определенная страница уже загружена, она получит только событие Windows.UI.WebUI.WebUIApplication.onactivated, не получив другие.

Сейчас, однако, давайте сконцентрируемся на работе с этим базовым процессом загрузки и, так как вы обычно выполняете работу по инициализации внутри события activated, рассмотрим его структуру поближе.

Врезка: Кодировка файлов для лучшей производительности при загрузке

Для того, чтобы оптимизировать генерирование байт-кода при обработке HTML, CSS и JavaScript-файлов, Магазин Windows требует, чтобы все .html, .css и .js-файлы были сохранены в кодировке UTF-8. Это установлено по умолчанию для всех файлов, создаваемых в Visual Studio или в Blend. Если вы импортируете активы из других источников, проверьте их кодировку. В диалоге Сохранить как (Save As) в Visual Studio (в Blend сейчас нет этой возможности), выберите Сохранить с кодировкой (Save with Encoding) и установите кодировку в Юникод (UTF-8, с сигнатурой), кодовая страница 65001 (Unicode (UTF-8 with signature) - Codepage 65001). Комплект сертификации приложений для Windows (Windows App Certification Kit) выдаст предупреждение, если обнаружит файлы не в этой кодировке.

В том же духе, минимизация JavaScript-кода не особенно важна приложениям для Магазина Windows. Так как пакет приложения загружается из Магазина Windows целиком и часто содержит другие активы, которые гораздо больше, чем ваши файлы с программным кодом, минимизация здесь не играет большой роли. Когда пакет установлен, генерация байт-кода подразумевает, что JavaScript-файлы в пакете уже обработаны и оптимизированы, в итоге, минимизация не даёт дополнительного выигрыша в производительности.

Ветви кода активации

Как мы видели в "Быстрый старт" , новый проект, создаваемый в Visual Studio или в Blend даёт вам следующий код в файле js/default.jd (некоторые комментарии удалены):

(function () { "use strict";

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

app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
if (args.detail.previousExecutionState !==
activation.ApplicationExecutionState.terminated) {
// TODO: Это приложение было вновь запущено. Инициализируйте
// приложение здесь.
} else {
// TODO: Это приложение было вновь активировано после приостановки.
// Восстановите состояние приложения здесь.
}
args.setPromise(WinJS.UI.processAll());
}
};

app.oncheckpoint = function (args) {
};

app.start();
})();

Пройдёмся по этому коду для того, чтобы пересмотреть то, что мы уже знаем и завершить понимание структуры этого базового кода:

  • (function () { … })(); содержащая всё, это, основа, шаблон модуля JavaScript.
  • "use strict" предписывает интерпретатору JavaScript применить Строгий режим (Strict Mode) (http://msdn.microsoft.com/library/br230269.aspx), функцию ECMAScript 5. Это проверка для неоптимальных методов программирования, таких, как использование неявно объявленных переменных, в итоге, его стоит оставить там, где он есть.
  • var app = WinJS.Application; и var activation = Windows.ApplicationMode.Activation; оба создают существенно сокращенные псевдонимы для часто используемых пространств имен. Это обычный подход для упрощения множественных ссылок на одни и те же части WinJS или WinRT.
  • app.onactivated = function (args) {…} назначает обработчик событию WinJS.UI.onactivated, которое является оболочкой для события Windows.UI.WebUI.WebUIApplication.onactivated. В этом обработчике:
    • args.detail.kind идентифицирует тип активации.
    • args.detail.previousExecutionState идентифицирует состояние приложения до активации, что определяет, нужно ли перезагружать состояние сеанса работы.
    • WinJS.UI.processAll создаст экземпляры элементов управления WinJS - то есть, элементы, которые содержат атрибут data-win-control , как мы рассмотрим в "Элементы управления, их стилизация и привязка данных" , "Элементы управления, их стилизация и привязка данных".
    • args.setPromise указывает Windows ждать до тех пор, пока завершится WinJS.UI.processAll, прежде чем убирать экран-заставку (смотрите раздел "Задержанная активация" дальше в этой лекции).
  • app.oncheckpoint получает пустой обработчик в шаблоне: мы остановимся на этом в разделе "Переход между событиями жизненного цикла приложений".
  • app.start() (WinJS.Application.start()) инициирует обработку событий, которые WinJS поставил в очередь при запуске.

Обратите внимание на то, как мы не обрабатываем напрямую любые события, запускаемые Windows, наподобие DOMContentLoaded или Windows.UI.WebUI.WebUIApplication.onactivated. Может быть, мы просто игнорируем эти события? Вовсе нет: один из удобных сервисов, которые WinJS предоставляет посредством WinJS.UI.Application - это упрощённая структура активации и других событий времени жизни приложения. Совершенно необязательно, но очень полезно.

В случае со start, например, происходит пара вещей. Во-первых, объект WinJS.Application прослушивает различные события, которые исходят из различных источников (DOM, WinRT и других) и собирает их в один объект, с которым вы регистрируете ваши собственные обработчики. Во-вторых, когда WinJS.Application принимает события активации, он не просто передает их в обработчики приложения, так как таких обработчиков, на самом деле, может и не быть. Поэтому он устанавливает эти события в очередь до тех пор, пока приложение не сообщит о том, что оно действительно готово, вызывая start. В этот момент WinJS проходит по очереди и запускает эти события. Вот и всё, что нужно сделать.

Как показывает код из шаблона, приложения обычно выполняют большую часть работы по инициализации в событии activated, где существует несколько потенциальных ветвей кода, прохождение по которым зависит от args.details (объект IActivatedEventArgs (http://msdn.microsoft.com/library/windows/apps/windows.applicationmodel.activation.iactivatedeventargs.aspx)). Если вы посмотрите документацию по WinJS.Application.onactivated (http://msdn.microsoft.com/library/windows/apps/br212679.aspx), вы увидите, что реальное содержимое args.details зависит от конкретного вида активации. Все виды активации, однако, имеют три общих свойства:

Таблица 3.3.
args.details Свойства Тип (в Windows.Application-Model.Activation) Описание
Kind ActivationKind (http://msdn.microsoft.com/library/windows/apps/windows.applicationmodel.activation.activationkind.aspx) Причина активации. Возможные значения launch (наиболее типично); search, shareTarget, file, protocol, fileOpenPicker, fileSavePicker, contactPicker, и cachedFileUpdater (для обслуживания контрактов); и device, printTask, Settings, cameraSettings (обычно используется приложениями, работающими с устройствами). Для каждого поддерживаемого типа активации, приложение будет иметь соответствующий путь инициализации.
previousExecutionState ApplicationExecutionState (http://msdn.microsoft.com/library/windows/apps/windows.applicationmodel.activation.applicationexecutionstate.aspx) Состояние приложения до данной активации. Возможные значения notRunning, running, suspended, terminated, и closedByUser. Обработка случая terminated наиболее распространена, так как в данном случае вам потребуется восстановить ранее сохраненное состояние сеанса работы с приложением (смотрите "Переход между событиями жизненного цикла приложений").
splashScreen splashScreen (http://msdn.microsoft.com/library/windows/apps/windows.applicationmodel.activation.splashscreen.aspx) Содержит событие ondismissed для тех случаев, когда экран-заставка не отображается. Так же содержит свойство imageLocation (Windows.Foundation.Rect) с координатами отображения экрана-заставки, как отмечено в разделе "Расширенные экраны-заставки"

Дополнительные свойства предоставляют соответствующие данные по активации. Например, свойство launch предоставляет titleId и arguments от дополнительных плиток (смотрите "Быстрый старт" курса "Программная логика приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript и их взаимодействие с системой"). Тип активации search (следующий наиболее часто используемый) предоставляет queryText и language, protocol предоставляет uri и так далее. Мы увидим, как использовать многие из этих свойств в соответствующем им контексте, и иногда они применимы не к default.html, а к другим страницам. То, что включено в шаблон (и то, что мы уже используем в приложении вроде "Here My Am!"), в основном, касается обработки обычного процесса запуска приложения с плитки (или внутри отладчика Visual Studio).

События WinJS.Application

WinJS.Application не связан только с активацией - его цель - централизовать события от нескольких различных источников и превратить их в собственные события. Опять же, это позволяет приложению прослушивать события из одного источника (назначая обработчик с помощью addEventListener(<event>) или on<event>, поддерживается и то, и другое). Вот полный перечень этих событий и их источников (если поставлено в очередь, событие вызывается в WinJS.Application.start):

  • activated Ставится в очередь в локальном контексте для Windows.UI.WebUI.WebUIApplication.-onactivated. В веб-контексте, где WinRT неприменима, вместо этого ставится в очередь для DOMContentLoader (где тип запуска - launch, а previousExecutionState установлено в notRunning ).
  • loaded Cтавится в очередь для DOMContentLoader во всех контекстах6Utilities.ready (http://msdn.microsoft.com/en-us/library/windows/apps/br211903.aspx), посредством которой вы можете задать обратный вызов для DOMContentLoaded. Это используется внутри WinJS, на самом деле, для того, чтобы гарантировать, что любое обращение к WinJS.UI.processAll будет обработано после DOMContentLoaded.. В веб-контексте ставится в очередь перед activated.
  • ready Ставится в очередь после loaded и activated. Это событие - последнее из событий в цепочке событий активации.
  • error Вызывается, если возникает исключение при диспетчеризации другого события. (Если ошибка не обработана, она передаётся в window.onerror).
  • checkpoint Это событие сообщает приложению, когда следует сохранить состояние сеанса работы, которое понадобится при повторном запуске приложения из предыдущего состояния terminated. Это событие вызывается в ответ на событие документа beforeunload и на событие Windows.UI.WebUI.WebUIApplication.onsuspending.
  • unload Так же вызывается для beforeunload после того, как будет вызвано событие checkpoint.
  • settings Вызывается в ответ на Windows.UI.ApplicationSettings.SettingsPane.oncommandsrequested (Смотрите "Быстрый старт" курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript").

С большинством из этих событий (за исключением error и settings), args, которые вы получите, содержат метод, который называется setPromise. Если вам нужно произвести любую асинхронную операцию (вроде XmlHttpRequest), вы можете получить promise-объект для этой работы и передать его в setPromise вместо того, чтобы самостоятельно вызывать его then или done. WinJS, таким образом, не обработает следующее событие в очереди до тех пор, пока получение данного отложенного результата не будет выполнено. Отметим, чтобы быть честными, что нет разницы между этим подходом и обычным вызовом done у promise-объекта самостоятельно внутри событий loaded, ready и unload. А вот в случае с activated и checkpoint (в особенности в состоянии suspending) разница есть, так как Windows, в противном случае, полагает, что вы сделали всё, что нужно, как только вы возвратились из обработчика; подробнее об этом - в разделе "Задержанная активация". В итоге, если у вы выполняете асинхронные задачи в обработчиках этих событий, лучше всего использовать setPromise. Так как WinJS.UI.processAll - это сама по себе асинхронная операция, шаблон заключает её в оболочку из setPromise, в итоге, экран-заставка не исчезнет до тех пор, пока не буду созданы экземпляры элементов управления WinJS.

Я думаю, что вы сочтёте WinJS.Application удобным инструментом для ваших приложений, и это средство, кроме того, предоставляет еще некоторые возможности, как описано здесь: "Пространство имен WinJS.Application" (http://msdn.microsoft.com/library/windows/apps/br229774.aspx). Например, оно предоставляет свойства local, temp, roaming, и sessionState которые удобны при управлении состоянием приложения, как мы увидим позже в этой лекции и в "Быстрый старт" курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript".

Еще нужно сказать о методах queueEvent и stop. Метод queueEvent помещает событие в очередь, оно попадёт на диспетчеризацию, когда существующие элементы выйдут из очереди, любым прослушивателем события, который вы установили с помощью WinJS.Application. События просто идентифицируются по строке, в итоге, вы можете ставить в очередь события с любым именем, которое вам нравится, и вызывать WinJS.Application.addEventListener с тем же самым именем в любом месте приложения. Это можно использовать для централизации пользовательских событий, вызываемых и при старте и в другое время в процессе выполнения приложения без создания отдельной глобальной функции для подобных целей. Кроме того, это мощное средство, с помощью которого раздельно объявленные, независимые компоненты, могут вызывать события, которые агрегирует один обработчик. (В качестве примера использования queueEvent смотрите Сценарий 2 в примере "Модель приложения" (http://code.msdn.microsoft.com/windowsapps/ApplicationModel-Sample-4be6575d)).

Что касается stop, это событие предоставляется для помощи во время модульного тестирования, во время которого вы можете симулировать различные последовательности активации, не перезапуская приложение и так или иначе симулировать нужные условия при перезапуске. Когда вы вызываете stop, WinJS удаляет прослушиватели событий, очищает очередь событий и очищает объект sessionState, но приложение продолжает работать. Затем вы можете вызвать queueEvent для того, чтобы заполнить очередь событий теми событиями, которыми хотите, и затем снова вызвать start для того, чтобы обработать эту очередь. Этот процесс может повторяться столько раз, сколько нужно.

Расширенные экраны-заставки

Сейчас, хотя экран-заставка, отображаемый по умолчанию, позволяет привлечь внимание пользователя, пользователь не может наблюдать за ним, если тот же самый экран отображается действительно долго. На самом деле, "действительно долго" для типичного пользователя - это около 15 секунд, после чего он начинает полагать, что приложение зависло и возвращается на Начальный экран для того, чтобы запустить другое приложение, которое не будет бесполезно тратить его время.

Честно говоря, до тех пор, пока пользователь держит ваше приложение на переднем плане и не переключается, Windows даёт приложению всё необходимое ему время. Но когда пользователь переключается на Начальный экран или на другое приложение, вы ограничены 15-ю секундами. Если ваше приложение не на переднем плане, Windows даёт приложению 15 секунд на то, что приложение выполнит то, что есть в app.start и вызовет событие activated, в этот момент домашняя страница должна быть отрисована. В противном случае, бабах! Windows автоматически завершает ваше приложение.

Первое условие, конечно, заключается в том, чтобы оптимизировать процесс загрузки для того, чтобы он был как можно более быстрым. Но, всё таки, иногда приложениям, на самом деле, нужно больше, чем 15 секунд для того, чтобы запуститься, в особенности при первом запуске после установки, в итоге, ему следует дать пользователю знать о том, что что-то происходит. Например, пакет приложения может содержать изрядное количество сжатых данных, когда оно загружено из Магазина Windows, и которые должны быть распакованы в локальную файловую систему при первой загрузке, в итоге, последующие запуски будут происходить гораздо быстрее. Многие игры поступают так с графикой и другими ресурсами, оптимизируя локальное хранение данных под характеристики устройства. Другие приложения могут заполнять локальную IndexedDB из данных, хранящихся в JSON-файле или загружать и кэшировать данные из онлайнового сервиса.

Возможно, что пользователь попытается загрузить ваше приложение вскоре после перезагрузки системы, в таком случае система может быть загружена множеством дисковых операций. Если вы загружаете данные с диска при активации приложения, этот процесс может занять больше времени, чем обычно.

Во всех эти случаях, всегда, когда приложение рискует превысить лимит в 15 секунд, вам понадобится реализовать расширенный экран-заставку (extended splash screen). Это подразумевает скрытие вашей реальной домашней страницы за другим элементов div, который выглядит точно так же, как системный экран-заставка, однако, находится под контролем приложения, и, в итоге, способен отображать индикаторы прогресса или другие элементы интерфейса, пока происходит инициализация приложения.

В целом, Microsoft рекомендует, чтобы расширенный экран-заставка совпадал с системным для того, чтобы избежать мерцания и резкого изменения изображения. (Смотрите материал "Руководство и контрольный список для экранов-заставок" (http://msdn.microsoft.com/library/windows/apps/hh465338.aspx)). В этот момент многие приложения просто добавляют индикатор прогресса и сообщение вроде: "Пожалуйста, возьмите напиток, выполните несколько физических упражнений или насладитесь несколькими минутами медитации, пока мы всё загрузим". Соответствие системному экрану-заставке, однако, не означает, что расширенный экран-заставка должен действовать подобным образом. Многие приложения, стартуют с копией системного экрана-заставки и затем используют анимированную графику на одной из его сторон, чтобы освободить место для других элементов. Другие приложения плавно скрывают существующие изображения и запускают видео.

Создание плавного перехода - это цель объекта args.detail.splashScreen, включенного в событие activated. Этот объект (смотрите: "Windows.ApplicationModel.Activation.SplashScreen" (http://msdn.microsoft.com/library/windows/apps/windows.applicationmodel.activation.splashscreen.aspx)) содержит свойство imageLocation (типа Windows.Foundation.Rect), которое содержит данные о расположении и размере изображения для экрана-заставки. Так как ваше приложение может быть запущено на устройствах с экранами различных размеров, это подсказывает вам где расположить то же самое изображение на вашей странице, где начать анимацию, и/или где поместить объекты вроде сообщений и индикаторов прогресса, связанных с данным изображением.

Объект splashScreen, кроме того, предоставляет событие ondismissed, в итоге вы можете произвести специфические действия, когда системный экран-заставка исчезает и появляется первая страница вашего приложения. Обычно это удобно для того, чтобы начать анимацию на странице, начать проигрывание видео и так далее.

Для того, чтобы увидеть пример расширенного экрана-заставки, обратитесь к примеру "Экран-заставка" (http://code.msdn.microsoft.com/windowsapps/Splash-screen-sample-89c1dc78). Еще одна деталь, о которой важно упомянуть, заключается в том, что так как экран-заставка - это обычная страница в вашем приложении, она может быть помещена в различные режимы просмотра - в такие, как режим прикрепленного просмотра. В итоге, как и со всеми остальными страницами вашего приложения, убедитесь в том, что расширенный экран-заставка поддерживает эти состояния!

Задержанная активация

Как упоминалось ранее, как только вы вернетесь из события activated, Windows считает, что вы сделали всё, что нужно, при старте приложения. По умолчанию, таким образом, Windows удалит свой экран-заставку и сделает домашнюю страницу приложения видимой. Но что, если вам нужно завершить одну или более асинхронных операций до того, как домашняя страница будет действительно готова, например, завершить WinJS.UI.processAll?

Это, снова, то, для чего существует метод args.setPromise внутри события activated. Если вы установили для асинхронной операции отложенный результат, использовав setPromise, Windows будет ждать до тех пор, пока отложенный результат не будет получен, и только тогда скроет экран-заставку. Шаблоны используют этот метод для того, чтобы экран-заставка отображался до тех пор, пока не будет завершен WinJS.UI.processAll.

Так как setPromise просто ожидает окончание выполнения отдельной отложенной операции, как обработать несколько асинхронных операций? Вы можете сделать это парой способов. Во-первых, если вам нужно управлять последовательностью подобных операций, вы можете связать их в цепочку, так, как мы уже это умеем - просто убедитесь в том, что в конце цепочки promise-объектов находится тот, который служит аргументом для setPromise - не вызывайте его метод done (вместо этого, если нужно, используйте then)! Если последовательность исполнения неважна, но вам нужно, чтобы все операции завершились, вы можете скомбинировать эти отложенные результаты, используя команду WinJS.Promise.join, передавая результат в setPromise. Если вам нужно, чтобы завершилась лишь одна операция, вы, вместо вышеупомянутой, можете использовать WinJS.Promise.any. Команды join и any будут разъяснены в последнем разделе этой лекции.

Другой подход заключается в том, чтобы зарегистрировать более чем один обработчик с WinJS.Application.onactivated; каждый обработчик получит собственные аргументы события и собственную функцию setPromise, и WinJS объединит эти возвращенные promise-результаты с помощью WinJS.Promise.join.

Метод setPromise из WinJS, на самом деле, реализован с использованием более общего механизма отложенных операций из WinRT. Объект args, передаваемый в Windows.UI.WebUI.WebUIApplication.onactivated (событие WinRT), содержит небольшой метод, который называется getDeferral (технически - Windows.UI.WebUI.ActivatedOperation.getDeferral (http://msdn.microsoft.com/library/windows/apps/windows.ui.webui.activateddeferral.aspx)). Эта функция возвращает отложенный объект, который содержит метод complete, и Windows не скроет системный экран-заставку до тех пор, пока вы не вызовете этот метод (хотя, это не меняет тот факт, что пользователи нетерпеливы, и ваше приложение всё еще ограничено 15-секундным лимитом). Код может быть похож на этот:

//В обработчике события activated 
var activatedDeferral = Windows.UI.WebUI.ActivatedOperation.getDeferral();

someOperationAsync().done(function () {
//После завершения инициализации activatedDeferral.complete();
}

Конечно, setPromise, в конечном счете, делает то же самое, и если вы прямо добавите обработчик события WinRT activated, вы сможете реализовать ту же задержку активации своими силами.