С Windows 8 пользователи всегда находятся на связи. Они могут сохранять подключение к Интернету, облачным службам и другим своим компьютерам под управлением Windows 8. Ваше приложение может участвовать в этой экосистеме с помощью перемещения данных приложения. В этой статье я подробно расскажу о перемещении данных приложения: что это такое, почему это важно, а главное — как с легкостью реализовать это в своем приложении.

Зачем перемещать данные

Перемещение параметров персонализации необходимо для поддержания подключения к Windows. И Windows 8 выполняет перемещение для многих параметров Windows, таких как тема рабочего стола, фоновые рисунки и элементы списка "Избранное" в браузере. Но пользовательская персонализация вовсе не ограничивается параметрами Windows. Приложения являются краеугольным камнем в формировании непрерывного опыта работы с Windows 8. Именно ваши приложения радуют пользователей Windows, именно с вашими приложениями пользователи работают основную часть времени. Хотя такие приложения, как Bing Weather и Bing Sports уже имеют функцию перемещения данных, нам нужна ваша помощь, чтобы доработать концепцию непрерывного подключения к Windows 8.

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

Как мы упростили задачу

Мы поставили перед собой цель: сделать перемещение данных как можно проще, чтобы эта функция получила практическое применение. Мы решили избавить вас — разработчиков — от решения задач, связанных с синхронизацией, поскольку они трудоемки и сложны. Мы хотели дать вам простую возможность перемещать любые данные, которые пользователь может настраивать.

Для этого в Windows 8 имеется встроенная функция синхронизации при перемещении данных приложения, действующая для всех приложений в стиле Metro с помощью подключенной учетной записи Майкрософт, связанной с пользователем. Класс ApplicationData делится на три типа данных, которые мы называем размещениями: локальные, перемещаемые и временные. Просто записывая свои данные в перемещаемое размещение, ваше приложение может участвовать в синхронизации данных с помощью подключенной учетной записи Майкрософт. Это значит, что вам не нужно беспокоиться об управлении отношениями синхронизации, настройке учетной записи и учетных данных, покупке службы или управлении ею, или о прочих хлопотных вопросах. Об этом за вас позаботится Windows. Вам нужно сосредоточиться лишь на том, какие данные перемещать и как спроектировать свое приложение с учетом этой полезной функции. Когда пользователи подключаются к Windows, они также подключаются и к вашему приложению.

Блок-схема, изображающая перемещение данных между вашим компьютером, локальным хранилищем и облачным хранилищем

Пользовательские данные и данные приложения

Прежде чем продолжить, важно понять разницу между пользовательскими данными и данными приложения при работе с перемещением данных. Пользовательские данные создает пользователь, и он же управляет ими в ходе работы с приложением; это могут быть документы пользователя, музыка, видеофайлы и изображения. Это могут быть вообще любые данные, которые пользователь считает ценными или которыми могут обмениваться приложения. Данные этого типа должны храниться в одной из библиотек KnownFolder или перемещаться с помощью API SkyDrive. Для хранения и перемещения паролей следует всегда применять PasswordVault. Эта статья блога охватывает данные, создаваемые и управляемые приложением, такие как параметры, настройки и состояние. Различия между пользовательскими данными и данными приложения, а также принципы их перемещения собраны в следующей таблице.

Пользовательские данные

Данные приложения

Могут использоваться несколькими приложениями

Значимы только для приложения, в котором они созданы

Документы, музыка, изображения, экспортированные данные

Параметры, настройки, контекст, состояние приложения

Хранятся в облаке с использованием SkyDrive

Перемещаются с помощью ApplicationData

Реализация принципа "настроить один раз, использовать везде"

Начнем с реализации простого принципа "настроить один раз, использовать везде". Допустим, у меня есть приложение — простое средство чтения RSS, позволяющее пользователю читать новости из набора каналов. При просмотре конкретного канала приложение отображает определенное число новостей на странице. С помощью настраиваемого пользователем параметра ItemsPerPage я могу задавать число новостей, отображаемых на странице. Я хочу сделать так, чтобы можно было задать этот параметр на одном компьютере и перемещать его на другие компьютеры, на которых установлено мое приложение. В классе ApplicationData имеется свойство RoamingSettings, поэтому обеспечить перемещение параметра столь же просто, как и записать его в качестве значения в RoamingSettings.

JavaScript:

Windows.Storage.ApplicationData.current.roamingSettings.values[“ItemsPerPage”] = 10

C#:

Windows.Storage.ApplicationData.Current.RoamingSettings.Values[“ItemsPerPage”] = 10;

Вот и все! Все процедуры синхронизации выполняет Windows, и теперь этот параметр будет синхронизироваться между всеми компьютерами пользователя, на которых установлено мое приложение, без дальнейших действий с моей стороны. Обычно этот параметр отображается на чудо-кнопке параметров приложения. Я очень рекомендую по умолчанию перемещать все параметры приложения. Однако некоторые параметры могут относиться к конкретному компьютеру, и их не следует сохранять в перемещаемых размещениях.

Если требуется записать файл вместо параметра, класс ApplicationData также предлагает свойство RoamingFolder, функционирующее аналогичным образом. Если для перемещения данных вы предпочитаете использовать файл, проследите, чтобы все открытые дескрипторы, относящиеся к этому файлу, были закрыты, когда запись будет закончена. Файлы с открытыми дескрипторами не перемещаются.

Планирование квоты перемещения

Если в своем приложении вы используете только простые параметры, тогда можно ограничиться тем, что мы уже рассмотрели. Но как быть со списком избранного или коллекцией, или с более крупными объемами данных? Насколько велики они могут быть? Функция перемещения данных приложения оптимизирована для параметров и настроек приложения и в ней заложена квота хранилища, соответствующая этим типам данных. Эта квота устанавливается сообразно системным ресурсам. Долгое время работы батареи и производительность системы являются важными характеристиками Windows 8, и квота лишь способствует тому, чтобы перемещение выполнялось без ущерба для них. Получить значение этой квоты можно с помощью свойства RoamingStorageQuota класса ApplicationData. На момент написания статьи квота составляла 100 КБ. С учетом квоты рекомендуется планировать использование данных приложения в ходе проектирования, чтобы не допустить превышения квоты.

Что происходит в случае превышения RoamingStorageQuota? Ничего! Точнее, никакие данные не перемещаются. Приложение не прервет работу и продолжит читать и записывать данные из перемещаемых размещений. Но пока общий объем перемещаемых данных в перемещаемых размещениях не станет меньше RoamingStorageQuota, эти данные не будут синхронизированы в облако.

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

При планировании приложения лучше не использовать громоздкие наборы данных. Любые расширяемые наборы данных, такие как списки избранного, следует ограничивать, чтобы ваше приложение всегда оставалось в рамках квоты перемещения. Возвращаясь к примеру со средством чтения RSS, допустим, что мне требуется сохранить список RSS-каналов — это список, управляемый пользователем. Для этого нужно какие-либо данные, которые обычно не ограничены, перевести в ограниченный режим. Проведем небольшую оценку. Допустим, мне нужно выделить 20 КБ на списки RSS-каналов. Для упрощения расчетов будем использовать оценку 80 байт на URL-адрес. Тогда в 20 КБ поместятся 250 URL-адресов. Можно и еще больше, если сократить URL-адреса, но 250 каналов — это, пожалуй, даже больше, чем моему приложению когда-либо понадобится. Мне нужно лишь ограничиваться этим пределом, записывать перечень каналов в файл и сохранять его в папке RoamingFolder.

Обеспечение непрерывного опыта работы на разных ПК

Вы можете добавить в свое приложение еще одну замечательную особенность, связанную с перемещением данных, — обеспечение непрерывного опыта работы на разных ПК! Вообразите ситуацию: пользователь у себя дома работает с моим приложением на настольном компьютере, просматривая RSS-каналы, а затем ему нужно успеть на автобус. Выходя из дома, он берет с собой планшетный компьютер с Windows 8 и открывает мое приложение. Мне нужно, чтобы он смог продолжить чтение именно с того места в тексте, где закончил читать на настольном компьютере. Обеспечение непрерывности состоит в том, чтобы сохранять и перемещать контекст действий пользователя.

В функциональном отношении это не отличается от перемещения любого другого параметра, но этот сценарий несколько иной, чем для большинства параметров. Пользователь может переходить с одного RSS-канала на другой очень быстро, и этот параметр может часто меняться, а другие параметры обычно нет. Более того, для оптимальной эфф��ктивности у пользователя должна быть возможность продолжить работу с приложением именно с того места, на котором она была прервана. Чтобы обеспечить пользователям такую возможность, мы создали уникальное имя параметра HighPriority. Чтобы применять его, просто назовите параметр в корневом контейнере RoamingSettings именем HighPriority. Он используется как любой другой параметр. Обработчик перемещения позволяет этому параметру перемещаться гораздо быстрее, чем другие перемещаемые данные, что и дает нужный результат.

Чтобы использовать это в моем средстве чтения RSS, достаточно переместить идентификатор RSS-канала. Запуская приложение или возобновляя работу с ним, я проверяю идентификатор и перехожу на соответствующий RSS-канал. Это очень похоже на мой предыдущий параметр, с той разницей, что теперь используется имя HighPriority.

JavaScript:

Windows.Storage.ApplicationData.current.roamingSettings.values[“HighPriority”] = currentFeedId;

C#:

Windows.Storage.ApplicationData.Current.RoamingSettings.Values[“HighPriority”] = currentFeedId;

Как и в прочих вариантах перемещения, всю самую сложную часть выполняет Windows, поэтому вам не о чем беспокоиться. Главное в применении параметра HighPriority — знать, когда его нужно читать, а когда записывать. Обычно следует проверять параметр HighPriority при запуске приложения или при возобновлении работы с ним, чтобы пользователь мог продолжить работу с того места, где он прервался, неважно, тот же это компьютер или другой. Мы записываем HighPriority при таких действиях пользователя, как переход на новую страницу или щелчок по ссылке.

Часто параметр HighPriority является одномоментным, но иногда он переполняется из-за операций быстрой записи, поэтому лишние записи только ухудшат производительность приложения, а не повысят эффективность перемещения данных. Как правило, параметр HighPriority представляет, где и что делает пользователь, например при переходе с одной страницы приложения на другую или просмотре контента. В некоторых приложениях данные быстро меняются, например в видеоплеере при воспроизведении видеофайлов ведется учет времени. Было бы излишне вносить записи в HighPriority при каждом изменении показаний счетчика видео, но вместо этого можно обновлять данные при изменении состояния, например с "Воспроизведение" на "Пауза", при достижении пользователем контрольной точки или в момент приостановки приложения.

Поддержание целостности данных

Некоторые данные тесно взаимосвязаны и должны всегда перемещаться вместе. Классический пример — координаты точки. Вы ведь не хотите, чтобы координаты X и Y в случае их изменения перемещались по отдельности, иначе данные могут быть повреждены, а полученные точки будут недопустимыми. Единицами перемещения для класса ApplicationData являются параметры и файлы, поэтому все данные в пределах одного файла будут всегда перемещаться вместе, как единое целое, и параметр тоже будет единым целым. Если требуется переместить несколько параметров вместе, например координаты, можно воспользоваться параметром CompositeSettingValue. Этот тип параметра позволяет группировать несколько параметров в одно значение, которое будет всегда перемещаться как единое целое.

Параметр HighPriority может быть и составным, что позволяет безопасно перемещать несколько фрагментов данных, представляющих текущее состояние вашего приложения. Например, мое средство чтения RSS группирует каналы по страницам для удобства чтения. Я вовсе не хочу, чтобы идентификатор канала и страница перемещались по отдельности, ведь в каналах бывает разное число страниц. Зато я хочу, чтобы перемещение идентификатора текущего канала и текущей страницы выполнялось в этом канале совместно в рамках параметра CompositeSettingValue — тогда будет обеспечена целостность данных.

JavaScript:

var currentFeed = new Windows.Storage.ApplicationDataCompositeValue();
currentFeed.insert(“CurrentFeedId”, currentFeedId);
currentFeed.insert(“CurrentFeedPage”, currentFeedPage);
Windows.Storage.ApplicationData.current.roamingSettings.values[“HighPriority”] = currentFeed;

C#:

Windows.Storage.ApplicationDataCompositeValue currentFeed = 
new Windows.Storage.ApplicationDataCompositeValue();
currentFeed.Insert(“CurrentFeedId”, currentFeedId);
currentFeed.Insert(“CurrentFeedPage”, currentFeedPage);
Windows.Storage.ApplicationData.Current.RoamingSettings.Values[“HighPriority”] = currentFeed;

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

Ответ на входящие изменения перемещаемых данных

Вам осталось узнать о последнем аспекте перемещения — о событии DataChanged класса ApplicationData. DataChanged — это просто событие, которое можно вызывать при каждом изменении данных приложения, например чтобы "сообщить" фоновой задаче о том, что пользователь изменил некоторый параметр. Когда перемещение данных в облаке вызывает локальное изменение в вашем приложении, Windows автоматически вызовет это событие для вас. Это позволяет реагировать на такие ситуации, когда данные с другого компьютера могли задержаться, а затем прибыть уже после того, как пользователь начал работать с вашим приложением. Можно использовать это событие, чтобы обновить представление данных или отреагировать на изменение параметров. Важно понимать, что эта возможность оптимизирована для пользователей, которые работают только на одном компьютере в отдельный момент времени, а затем переключаются на другой. Поэтому не следует использовать события DataChanged в качестве средства коммуникации между несколькими компьютерами в реальном времени.

Участие в концепции непрерывного подключения

Оснащение приложений возможностями перемещения данных является важной частью создания непрерывного подключения к Windows 8. И мы создали платформу, которая упрощает реализацию этих удобных новых возможностей. Перемещение в облако является важным плюсом для вашего приложения, и пользователи по достоинству оценят удобство этой функции и гибкость переходов между компьютерами. Дополнительные советы по перемещению данных можно найти в Рекомендациях по перемещению данных приложения. И обязательно ознакомьтесь с образцом класса ApplicationData, содержащим примеры всех случаев, описанных в этой статье. Спасибо за внимание!

-- Дэйв Беннетт (Dave Bennett), руководитель программы, Windows