Беларусь |
Состояния, параметры, файлы и документы
Использование API данных приложения для управления состоянием
Сейчас, когда мы ознакомились с сущностью API, посмотрим, как их можно использовать для работы с различными видами данных приложения, а так же рассмотрим специальные соглашения, которые применимы в данной работе
Состояние сеанса
Как было описано выше, состояние сеанса это то, что приложение сохраняет при приостановке, и, таким образом, может восстановить свое состояние после того, как было остановлено системой и запущено снова. Единственный вариант развития подобных событий – это остановка приложения системой, поэтому все, что включают в состояние сеанса, всегда должно быть рассчитано на то, чтобы давать пользователю иллюзию непрерывной работы приложения. В некоторых случаях, как описано в лекции курса "Введение в разработку приложений для Windows 8 с использованием HTML, CSS и JavaScript", вы можете, на самом деле, не восстанавливать это состояние, особенно, если приложение было остановлено в течение длительного времени и маловероятно, чтобы пользователь помнил, как все выглядело во время последнего сеанса работы. Это решение вам нужно будет принять для собственного приложения, от него зависит опыт взаимодействия пользователя и приложения.
Состояние сеанса следует сохранять в папке данных приложения localFolder , или в объекте localSettings . Не следует сохранять его в области временных данных, так как пользователь может запустить средство очистки диска в то время, когда приложение приостановлено или остановлено, и в таком случае данне состояния сеанса будут удалены (смотрите следующий раздел).
Объект WinJS sessionState самостоятельно создает файл, который называется _sessionState.json внутри localFolder. В этом файле хранится обычный текст в формате JSON, поэтому вы можете в любое время его просмотреть. Вы можете записать переменные сеанса работы в объект sessionState , в любое время, когда они изменяются, используя sessionState как пространство имен для этих переменных, и именно так следует поступать. При таком подходе эти значения сохраняются и перезагружаются автоматически, без необходимости управлять этими переменными где-либо еще.
Если вам нужно сохранить дополнительные значения внутри sessionState , прежде чем данные будут записаны, сделайте это в обработчике WinJS.Application.oncheckpoint . Хороший пример подобных данных – это навигационный стек элементов управления страниц, который доступен посредством WinJS.Navigation.history . Так же вы можете скопировать эти данные в sessionState внутри метода PageControlNavigation.navigated (он находится в navigation.js и предоставляется шаблонами проектов). В любом случае, у WinJS есть собственный обработчик checkpoint, который всегда вызывается последним (после вашего обработчика) для того, чтобы убедиться, что любые изменения, которые вы внесли в sessionState после этого события, были сохранены.
Если вы не используете объект WinJS sessionState , а просто используете API WinRT для работы с данными приложения, вы можете сохранять состояние сеанса в любое время (в том числе – в checkpoint ), и вам понадобится восстанавливать их в событии активации при выполнении условия previousExecutionState == terminated .
Кроме того, хорошей практикой является обеспечение некоторой устойчивости в обработке состояния сеанса: если загруженные данные кажутся неподходящими или имеются другие проблемы, можно вернуться к данным сеанса по умолчанию. Помните так же, что вы можете использовать контейнер localSettings с взаимосвязанными параметрами, что гарантирует то, что группа значений будет сохраняться и извлекаться как единое целое. Так же может оказаться полезным при разработке иметь команду, которая дает вам возможность очищать состояние сеанса в том случае, если оно заполняется ненужными данными, но, в то же время, обычная деинсталляция приложения так же очищает состояние сеанса. В то же время, нет необходимости предоставлять пользователям команду для очищения состояния приложения: если ваше приложение не может запуститься после завершения, флаг previousExecutionState будет иметь состояние notRunning , когда пользователь в следующий раз попытается запустить приложение, в подобной ситуации вы не будете пытаться восстановить состояние.
Кроме того, нет необходимости включать в состояние сеанса номер версии. Если пользователь установил обновление в то время, когда ваше приложение было приостановлено и остановлено, и версия данных приложения была изменена, значение previousExecutionState будет сброшено. Если по каким-либо причинам вы не изменяете версию данных приложения – например, если обновления весьма незначительны, тогда ранее сохраненные данные состояния приложения могут использоваться дальше. Но в данном случае перед нами – то же самое приложение, поэтому управление версиями состояния сеанса не требуется.
Врезка: использование sessionStorage и localStorage HTML5
Если хотите, вы можете использовать объект HTML5 localStorage для хранения данных состояния сеанса приложения и других данных приложения. Содержимое объекта хранится в папке localFolder . Содержимое localStorage не загружается до первой попытки доступа к нему и ограничено объемом в 10 Мб на приложение. API WinRT и WinJS, с другой стороны, ограничены лишь емкостью файловой системы.
Что касается объекта HTML5 sessionStorage , он, на самом деле, не нужен, когда вы используете элементы управления страниц и поддерживаете общий контекст скрипта для этих страниц, так как переменные, находящиеся в памяти уже выполняют нужную функцию. Однако, если вы изменяете контекст страниц, используете ссылки <a> или document.location для целей навигации, sessionStorage способен быть полезным. Кроме того, вы можете кодировать информацию в URI, как обычно делается в веб-приложениях.
И sessionStorage , и localStorage полезны внутри страниц iframe , исполняющихся в веб-контексте, так как API WinRT недоступны. В то же время, вы можете загрузить WinJS в веб-контекст (такая возможность поддерживается) и объекты WinJS.Application.local , roaming , и temp будут работать, используя буферы для данных, расположенные в памяти, вместо файловой системы.
Локальное и временное состояние
В отличие от состояния сеанса, которое восстанавливается лишь в особых обстоятельствах, локальное состояние приложения, которое состоит из этих параметров и других данных, всегда применяется при запуске приложения. Сюда попадает все, что пользователь может настроить, несмотря на то, что это так же часть перемещаемых данных, в таком случае эти данные так же загружаются при запуске приложения. Любые другие кэшированные данные, сохраненные результаты поиска, недавно использованные элементы, экранные элементы, предпочитаемые медиа-форматы, настройки, зависящие от устройства, так же попадают сюда. Коротко говоря, если какие-то данные не являются чистым состоянием сеанса, либо – частью перемещаемого состояния, это – либо локальное, либо временное состояние приложения. (Помните, что учетные данные следует хранить в Хранилище учетных данных вместо хранения их среди данных приложения).
Те же API, которые мы видели, работают и для этих видов состояния, включая все API WinRT, объекты WinJS.Application.local и temp , и HTML localStorage . Так же вы можете использовать HTML5 API IndexedDB, SQLite, и HML App Cashe – это лишь другие формы локальных данных приложения.
При работе с локальными и временными данными очень важно назначать им номер версии, так как они сохраняются и при обновлении приложения (хотя временное состояние в это время очищается). В процессе любого обновления приложения будьте готовы к тому, чтобы загрузить старую версию состояния приложения и выполнить необходимые обновления, или просто решить, что версия слишком стара и очистить данные (Windows.Storage.ApplicationData.current.clearAsync ), прежде чем задавать новые значения по умолчанию. Как упоминалось выше, возможно осуществить перенос состояния с использованием фоновой задачи (смотрите Главу 2 курса "Программная логика приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript и их взаимодействие с системой").
Вообще говоря, локальные и временные данные приложения – это одно и то же – они имеют одинаковые API, и хранятся в папках, расположенных в одном и том же месте. Временные данные, однако, не поддерживают параметры и контейнеры параметров. Другое различие заключается в том, что содержимое в папке временных данных (вместе с HTML5-кэшем приложения) могут подвергнуться воздействию средства очистки диска Windows. Это означает, что временные данные могут исчезнуть в любой момент, когда пользователь захочет освободить немного дискового пространства. Так же вы можете использовать фоновую задачу с триггером обслуживания для самостоятельного выполнения очистки (опять же, смотрите Главу 2 курса "Программная логика приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript и их взаимодействие с системой").
По этим причинам, временные данные следует использовать для хранения информации, которая оптимизирует производительность приложения, но не для данных, которые критически важны для работы приложения. Например, если в пакете приложения имеется JSON-файл, который вы обрабатываете или распаковываете при первом запуске программы, чтобы в дальнейшем приложение работало быстрее, и вы не выполняете никаких изменений этих данных из приложения, вы можете решить хранить это среди временных данных. То же самое справедливо для графических ресурсов, которые вы можете обработать для применения на конкретном устройстве, на котором исполняется приложение. Вы всегда можете повторить этот процесс, воспользовавшись исходным источником, таким образом, эти данные – так же хороший кандидат для хранения среди временных данных. Похожим образом, если вы получили данные из онлайнового сервиса для целей оптимизации производительности (таким образом, вы можете обновлять локальные данные инкрементно), вы всегда можете запросить их снова. Это особенно полезно для обеспечения возможности работы без подключения к сети, хотя в некоторых случаях может понадобиться предоставить пользователям выбрать, следует ли сохранять эту информацию среди локальных данных приложения или среди временных (параметр, который может появиться в интерфейсе чудо-кнопки Параметры вместе с командой, которая позволяет очистить кэш).
Врезка: AppCache HTML5
Приложения для Магазина Windows могут использовать кэш приложения HTML5 как часть стратегии кэширования и работы в оффлайновом режиме. Это особенно полезно в элементах веб-контекста iframe, где этот механизм можно использовать для любого содержимого. Например, приложение для чтения книг в онлайн-режиме может показывать содержимое в iframe, и если страницы включают теги кэша приложения, они будут сохраняться и будут доступны в режиме, когда сетевое соединение недоступно. В локальном контексте, кэш приложения работает для неисполняемых ресурсов, таких, как изображения, аудио, видео, но не для HTML или JavaScript.
IndexedDB и другие технологии баз данных
Многие виды локальных данных приложения прекрасно подходят для хранения в базе данных. В приложениях для Магазина Windows API IndexedDB доступно посредством объектов window.indexedDB и worker.indexedDB . Подробности об этом вы можете узнать в спецификациях W3C (https://dvcs.w3.org/hg/IndexedDB/), в справочных материалах по Indexed Database API (http://msdn.microsoft.com/library/windows/apps/hh466139.aspx) и в примере "IndexedDB" (http://code.msdn.microsoft.com/windowsapps/IndexedDB-sample-eb1e95af).
Хотя база данных IndexedDB хранится среди локальных данных приложения, знайте, что существуют некоторые ограничения, так как нет средств, с помощью которых приложение или операционная система могут уменьшить размер файла базы данных и очистить неиспользуемое пространство:
- У IndexedDB есть ограничение в 250 Мб на приложение и общий системный лимит в 375 Мб на жестких дисках меньше 32 Гб, или 4% (максимум – 20 Гб) на дисках, больше 32 Гб. Таким образом возможна ситуация, что ваше приложение может не иметь достаточно места для хранения данных, в подобном случае вам нужно иметь некий запасной механизм. (При превышении лимита API будет выдавать исключение "Quota Exceeded").
- IndexedDB в Windows 8 не поддерживает составные ключи – таким образом, сейчас не поддерживается несколько значений для ключа или индекса (multientry).
- По умолчанию, доступ к IndexedDB предоставляется только HTML-страницам, которые являются частью пакета приложения, и тем, которые объявлены как URI содержимого (смотрите раздел "Локальный и веб-контексты внутри хост-процесса приложения" Главы 3 курса "Введение в разработку приложений для Windows 8 с использованием HTML, CSS и JavaScript"). Произвольные веб-страницы, которые могут быть загружены в iframe , не имеют доступа к IndexeDB, преимущественно для того, чтобы не занимать место в базе данных, объем которой ограничен 250 Мб и сохранить его для страниц приложения. Однако, вы можете предоставить произвольным страница доступ, включив следующий тег в домашнюю страницу и не устанавливая атрибут src элемента iframe до тех пор, пока не будет запущено событие DOMContentLoaded или activated :
<meta name="ms-enable-external-database-usage" content="true"/>
Помимо IndexedDB существуют и другие технологии баз данных, доступные для приложений Магазина Windows. Для создания локальных реляционных баз данных попробуйте SQLite. Это API, которое хорошо подходит для приложений, написанных на языке наподобие C#, как описано в блоге Тима Хейера (http://timheuer.com/blog/archive/2012/08/07/updated-how-to-using-sqlite-from-windows-store-apps.aspx), но, к счастью, есть и версия, которая называется SQL.js, где SQLite скомпилирован для JavaScript с использованием Emscripten (http://badassjs.com/post/18857332551/sql-js-sqlite-compiled-to-javascript-via-emscripten). Очень хорошо! В сообществе разработчиков можно найти и другие решения для JavaScript.
Если вас беспокоят ограничения IndexedDB, вы можете воспользоваться API Win32 "Jet" или Extensible Storage Engine (ESE) (http://msdn.microsoft.com/library/windows/apps/br205753.aspx) (на них построена реализация IndexedDB). Для этого вам понадобится написать оболочку в виде компонента WinRT на C# или C++ (этому посвящена Глава 5 курса "Программная логика приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript и их взаимодействие с системой"), так как из JavaScript нельзя получить прямой доступ к этим API.
То же самое справедливо для API баз данных сторонних разработчиков. До тех пор, пока они используют лишь API Win32, использование которых разрешено приложениям для Магазина Windows (они перечислены на странице "Win32 и COM для приложения Магазина Windows" (http://msdn.microsoft.com/library/windows/apps/br205757.aspx)), они отлично работают.
Следует так же отметить, что Библиотека OData для JavaScript (http://www.odata.org/libraries#JavaScript) так же отлично работает с приложениями для Магазина Windows, реализуя доступ к онлайновым SQL-серверам, так как протокол OData работает посредством REST.
И, наконец, еще одна возможность для организации данных, хранящихся в файлах, по которым можно организовать поиск, заключается в использовании системного индекса (system index) путем создания папки с именем "Indexed" в локальной папке данных приложения. Содержимое файлов в этой папке будет проиндексировано системной службой индексирования и к этому содержимому можно обращаться посредством запросов, использующих Advanced Query Syntax (AQS) с помощью API, описанного ниже в разделе "Расширенные возможности запросов к файлам". Так же вы можете осуществлять поиск, основанный на свойствах Windows (http://msdn.microsoft.com/library/windows/desktop/dd561977.aspx), делая такой подход простой альтернативой использования баз данных.