Опубликован: 10.04.2013 | Уровень: для всех | Доступ: платный
Лекция 2:

Состояния, параметры, файлы и документы

API AppData (WinRT и WinJS)

Когда вы запрашиваете у Windows свойство Windows.Storage.ApplicationData.current, вы получаете объект Windows.Storage.ApplicationData (http://msdn.microsoft.com/library/windows/apps/br241587.aspx), который полностью настроен для вашего приложения. Вот, что содержит этот объект:

  • Свойства localFolder, temporaryFolder, и roamingFolder, каждое из которых является объектом Windows.Storage.StorageFolder, который позволяет вам создавать любые файлы и дополнительные структуры папок в соответствующих расположениях (но помните о параметре roamingStorageQuota, который описан ниже).
  • Свойства localSettings и roamingSettings, которые являются объектами Windows.Storage.ApplicationDataContainer (http://msdn.microsoft.com/library/windows/apps/windows.storage.applicationdatacontainer.aspx) и позволяют управлять иерархией контейнеров, состоящих из пар ключ-значение, или составными группами подобных пар значений. Все эти установки хранятся среди других данных приложения в папке Settings, в файле settings.dat.
  • Свойство roamingStorageQuota, которое содержит сведения об объеме данных, в килобайтах, которые Windows автоматически перемещает для целей приложения (обычно – 100). Если общий объем данных, сохраненных в папках roamingFolder и roamingSettings, превышает указанный лимит, перемещение будет приостановлено до тех пор, пока объем данных не упадет ниже квоты. Вы должны контролировать объем хранимых данных, если вы полагаете, что их объем близок к лимиту.
  • Событие dataChanged указывает на синхронизацию папок roamingFolder или roamingSettings с данными, хранящимися в облаке. По данному событию приложению следует повторно прочесть данные перемещаемого состояния. Это событие WinRT, для которого нужно использовать removeEventListener, как было описано в лекции 3 курса "Введение в разработку приложений для Windows 8 с использованием HTML, CSS и JavaScript".
  • Метод signalDataChanged вызывает событие dataChanged. Это позволяет вам объединить обновления локальных и перемещаемых состояний в одном обработчике для события dataChanged.
  • Свойство version и метод setVersionAsync предназначены для управления отметками версий данных приложения. Версии применимы к полному объему данных – к локальным, временным и перемещаемым данным. Отдельные версии для разных данных не предусмотрены.
  • Метод clearAsync позволяет очищать состояние всех папок AppData и контейнеров параметров. Используйте его, когда вы хотите повторно инициализировать состояние по умолчанию, что особенно полезно, когда вы перезапускаете приложение из-за нарушения данных его состояния.
  • Метод clearAsync(<locality>) это вариант clearAsync, который ограничен одним расположением (локальным, временным, перемещаемым). Расположение идентифицируется с помощью значения из Windows.Storage.ApplicationDataLocality, такое, как Windows.Storage.ApplicationDataLocality.local. В случае с локальными и перемещаемыми данными, содержимое обеих папок и содержимого контейнеров очищается. Параметр temp воздействует только на папку TempState.

Теперь давайте посмотрим на то, как использовать это API для управления различными видами состояния приложения, что включает в себя некоторые вспомогательные функции WinRT, используемые для тех же целей.

Подсказка. API, которые работают с состоянием приложения, вызывают события в Средстве просмотра событий (Event Viewer), если вы включили эту возможность, как было описано в лекции 3 курса "Введение в разработку приложений для Windows 8 с использованием HTML, CSS и JavaScript". Убедитесь в том, что функция Вид > Отобразить аналитический и отладочный журналы (View > Show Analytic and Debug logs) включена. Затем пройдите в раздел Application and Services Log (Журналы приложения и служб), разверните раздел Microsoft/Windows/AppModelState, где вы найдете группы Debug (Отладка) и Diagnostic (Диагностика).

Контейнеры параметров

Для начинающих, давайте посмотрим на свойства localSettings и roamingSettings, которые обычно называют контейнерами параметров (settings containers). Вы работаете с ними с помощью API ApplicationDataContainer, которое устроено довольно просто. Каждый контейнер имеет четыре свойства только для чтения: name (строка) , locality (значение из Windows.Storage.ApplicationDataLocality, здесь есть лишь значения local и roaming), и коллекции, которые называются values и containers.

Параметры контейнеров верхнего уровня имеют пустые имена. Свойство устанавливается на дочерние контейнеры, которые вы создаете с помощью метода createContainer (и удаляете с помощью deleteContainer). Эти дочерние контейнеры могут содержать другие контейнеры, что позволяет вам создавать иерархию настроек. Таким образом, эти контейнеры настроек предназначены для хранения небольших объемов данных, обычно – параметров пользователя, и отдельных параметров, объем которых ограничен 8 Кб, а так же любые наборы взаимосвязанных параметров (смотрите ниже) размером до 64 Кб. Учитывая эти ограничения, превышение объема в один мегабайт предусматривает довольно сложную иерархию настроек, которой сложно управлять, и доступ к которой осуществляется сравнительно медленно. Поэтому не поддавайтесь искушению воспринимать эти настройки как своего рода базу данных. Для этих целей гораздо лучше подходят иные механизмы, такие, как IndexedDB и SQLite, и с их помощью вы можете хранить любые объемы данных, так же, как и в папках AppData (помните об ограничении на объем перемещаемых данных, когда вы записываете данные в roamingFolder).

Для любого контейнера, который у вас есть, его коллекция containers – это объект IMapView (http://msdn.microsoft.com/library/windows/apps/br226037.aspx), с помощью которого вы можете просматривать содержимое контейнера. Коллекция values, с другой стороны, это обычный массив (с технической точки зрения – объект IPropertySet в WinRT, который проецируется в WinJS в виде массива с методами IPropertySet). Таким образом, хотя свойство values в любом контейнере – это свойство только для чтения, что означает, что вы не можете назначить ему какой-либо произвольный массив, вы можете управлять содержимым данного массива так, как вам нужно.

Мы можем увидеть это в примере "Данные приложения" (http://code.msdn.microsoft.com/windowsapps/ApplicationData-sample-fb043eb2), в котором есть много примеров базовых операций с данными приложения. Сценарий 2, например, (js/settings.js) показывает простоту использование массива localSettings.value:

var localSettings = Windows.Storage.ApplicationData.current.localSettings;
var settingName = "exampleSetting";
var settingValue = "Hello World";

function settingsWriteSetting() {
localSettings.values[settingName] = settingValue;
}

function settingsDeleteSetting() {
localSettings.values.remove(settingName);
}
 

Многие параметры, похожие на те, которые показаны выше, это простые пары ключ-значение, но другие параметры могут быть объектами с множеством свойств. Это являет собой особую проблему: хотя вы можете, конечно, записывать и считывать отдельные свойства данного объекта внутри массива values, что случится, если в одном из них произойдет сбой? Это приведет к тому, что состояние приложения окажется поврежденным.

Для защиты от этого API для работы с данными приложения предоставляет возможность работы с взаимосвязанными параметрами (composite settings) как с неделимой единицей. (Повторюсь, каждый набор взаимосвязанных параметров ограничен размером в 64 Кб). Это похоже на идеальное групповое сознание: либо все преуспеют, либо всех ждет неудача и ничего кроме этих двух вариантов! Таким образом, если возникает ошибка при чтении или записи любой части взаимосвязанных параметров, вся операция признается несостоявшейся. В случае с перемещаемыми данными, либо перемещается вся группа взаимосвязанных параметров, либо они не перемещаются вовсе.

Объект взаимосвязанных параметров создается с помощью Windows.Storage.ApplicationDataCompositeValue ( http://msdn.microsoft.com/library/windows/apps/windows.storage.applicationdatacompositevalue.aspx), как показано в Сценарии 4 примера работы с данными приложения (js/compositeSetting.js) нет такого сценария:

var roamingSettings = Windows.Storage.ApplicationData.current.roamingSettings;
var settingName = "exampleCompositeSetting";	
var settingName1 = "one";	
var settingName2 = "hello";	
function compositeSettingsWriteCompositeSetting() {
var composite = new Windows.Storage.ApplicationDataCompositeValue();
composite[settingName1] = 1; // пример значения	
composite[settingName2] = "world"; // пример значения
roamingSettings.values[settingName] = composite;
}	


function compositeSettingsDeleteCompositeSetting() {
roamingSettings.values.remove(settingName);
}


function compositeSettingsDisplayOutput() {	
var composite = roamingSettings.values[settingName];
// ...	
 }
 

Объект ApplicationDataCompositeValue имеет, как вы можете увидеть в документации, некоторые дополнительные методы и события для того, чтобы помочь в управлении им, это такие методы, как clear, insert и mapchanged.

Взаимосвязанные параметры, во многом, напоминают контейнер параметров, однако, они не могут содержать другие контейнеры. Важно не путать их с обычными контейнерами. Дочерние контейнеры внутри параметров используются лишь для создания иерархии (посмотрите Сценарий 3 примера). Взаимосвязанные параметры, с другой стороны, специально созданы для создания более сложных наборов параметров, которые работают как неделимая единица, подобное поведение не гарантировано для обычных контейнеров параметров.

Как упомянуто выше, все эти параметры записываются в файл settings.dat в папке приложения Settings. Так же полезно знать, что изменения, которые вы вносите в контейнеры параметров, автоматически сохраняются, хотя здесь и присутствуют встроенные функции пакетной обработки данных для предотвращения чрезмерной дисковой активности, когда вы изменяете множество значений подряд. В любом случае, вам не нужно беспокоиться о том, когда вы сохраняете значения. Система берет управление этим процессом на себя.

Управление версиями состояния приложения

С точки зрения Windows, локальное, временное и перемещаемое состояние – это части единого целого, и все они имеют одну и ту же версию. Номер версии устанавливается посредством Windows.Storage.ApplicationData.setVersionAsync (http://msdn.microsoft.com/library/windows/apps/windows.storage.applicationdata.setversionasync.aspx), прочитать номер версии можно, воспользовавшись свойством только для чтения Windows.Storage.ApplicationData.version. Если хотите, вы можете поддерживать собственную систему назначения версий, с помощью отдельного файла или параметра приложения. Однако, я рекомендую, чтобы вы избегали подобного с перемещаемым состоянием, так как сложно предсказать, как Windows будет управлять синхронизацией слегка отличающихся структур. Даже в случае с локальным состоянием, попытка играть в сложные игры версий, на самом деле, может оказаться гораздо сложнее, чем кажется, и, вероятно, подобного лучше избегать вообще.

Версия данных вашего приложения и версия приложения – это разные вещи. На самом деле, они никак не связаны. В то время, как версия данных приложения устанавливается с помощью setVersionAsync, версией приложения управляют в разделе Упаковка (Packaging). У вас может быть приложение, которое от версии 1.0.0.0 до версии 4.3.9.3 использует данные приложения версии 1.0.0.0, или, может быть, версия приложения 1.2.1.9 переходит на версию 1.0.1.0. данных приложения, и версия 2.1.1.3 использует версию 1.2.0.0 данных приложения. На самом деле, это неважно, до тех пор, пока вы контролируете этот процесс и старые данные приложения могут переходить к новым версиями приложений!

Переход (migration) происходит при вызове setVersionAsync, где второй параметр является функцией, которая конвертирует данные. Эта функция принимает объект SetVersionRequest (http://msdn.microsoft.com/library/windows/apps/windows.storage.setversionrequest.aspx), который содержит свойства currentVersion и desiredVersion, таким образом, показывая вашей функции, какого рода конверсия, на самом деле, нужна. В ответ, вам следует просмотреть все данные приложения и соответствующим образом осуществить перенос отдельных параметров и файлов. Как только вы вернетесь из обработчика конверсии, Windows решит, что переход завершен. Конечно, так как процесс часто задействует асинхронные файловые операции ввода-вывода, вы можете использовать отложенный механизм, наподобие того, который мы видели при активации приложения. Вызовите метод SetVersionRequest.getDeferral для того, чтобы получить объект для выполнения отложенных действий (SetVersionDeferral), и вызовите его метод complete, когда все асинхронные операции будут завершены. Примеры подобного можно найти в Сценарии 9 примера "Данные приложения" (http://code.msdn.microsoft.com/windowsapps/ApplicationData-sample-fb043eb2).

Можно осуществлять перенос данных приложения и тогда, когда устанавливается новое обновление приложения. Для этого пользуются фоновой задачей для вызова sevicingComplete. Смотрите Главу 2 курса "Программная логика приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript и их взаимодействие с системой", в особенности – раздел "Фоновые задачи и приложения на экране блокировки" ближе к концу.

Дмитрий Мельник
Дмитрий Мельник
Беларусь
Сергей Ширяев
Сергей Ширяев
Россия, г. Москва