Главная » C#, Windows Runtime, XAML, Разработка для Windows 8 » Хранение данных и жизненный цикл приложения

0

Хранение данных приложения

У  приложения  должна  быть  возможность сохранять  данные  —  настройки, сведения о состоянии и данные для будущей синхронизации. К тому же следует обеспечить  комфортную   работу   пользователя на   различных   устройствах. Данные, предназначенные для хранения, могут быть представлены и как набор переменных простых типов, и в виде файлов различной структуры. В связи с этим в Windows Runtime выделяют три способа хранения данных приложения.

·                   Локальные данные — все настройки сохраняются в  реестре или внутри файлов, ассоциированных  с конкретным пользователем.

·                   Роуминг данных — данные размещаются в облаке и могут использоваться приложением на различных устройствах.

·                   Временные данные — данные размещаются во  временном  хранилище и могут быть удалены в любой момент.

Рассмотрим детально каждый из механизмов хранения данных.

Хранение данных локально

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

«песочницы», то прямого доступа к реестру или файловой системе у  них нет. По этой причине  Windows Runtime предлагает специальный  набор классов, который позволяет хранить данные в  выделенном разделе реестра или папке, ассоциированной  с   конкретным    пользователем.  Представленные  классы выполняют  всю черновую работу. По большому счету, разработчик может и не догадываться, где хранятся данные.

Итак, если мы говорим о хранении простых типов в  реестре, то тут  доступны такие классы.

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

·                   ApplicationDataCompositeValue — этот класс позволяет собрать сложный тип данных на основании нескольких простых.  Фактически, указанный механизм облегчает группировку данных простых типов. Подобное можно сделать и с помощью вложенных контейнеров, но рассматриваемый класс более прост в использовании.

Перечисленные выше классы находятся в пространстве имен Windows.Storage и могут быть использованы без особых затруднений. Например, если Вы хотите получить контейнер по умолчанию или создать новый именованный контейнер, то можно применить следующий код.

ApplicationDataContainer current = ApplicationData.Current.LocalSettings;

ApplicationDataContainer named = current.CreateContainer(

"myContainer", ApplicationDataCreateDisposition.Always);

Этот   код   получает   ссылку   на   основной  контейнер,    ассоциированный с пользователем приложения, а затем создает вложенный контейнер.

Имея ссылку на контейнер, можно приступить к сохранению простых данных. Если речь идет о реестре, то поддерживаются следующие типы данных: Boolean, Double, Int32, Int64, Single, String, UInt8, UInt32, UInt64.

Код  ниже  демонстрирует, как  можно  добавить новую пару  ключ-значение в контейнер.

current.Values["myValue"] = 5; current.Containers["myContainer"].Values["mySecondValue"] = "Hello";

Как видите, в  примере присутствуют простые индексаторы, которые позволяют легко создать пару или получить значение по известному ключу.

Наконец,  если  Вы  хотите  создать  в   контейнере  комплексное  (композитное)

значение, то можно воспользоваться следующим кодом.

ApplicationDataCompositeValue composite = new ApplicationDataCompositeValue();

composite["firstVal"] = 1; composite["secondVal"] = "Hello";

current.Values["compValue"] = composite;

Гораздо интереснее работать с файлами. Для их хранения  приложению также выделяется отдельный контейнер, с которым  можно взаимодействовать  при помощи класса StorageFolder.

StorageFolder current = ApplicationData.Current.LocalFolder;

Созданный выше объект располагает множеством интересных методов.

·                   CreateFileAsync — создает файл.

·                   CreateFolderAsync — создает каталог.

·                   DeleteAsync — удаляет объект (файл или каталог).

·                   RenameAsync — позволяет выполнить переименование объекта.

·                   GetFileAsync — позволяет вернуть ссылку на файл с указанным именем

(объект типа StorageFile).

·                   GetFilesAsync — возвращает список файлов, соответствующих запросу.

·                   GetFolderAsync — возвращает указанный в параметрах каталог.

·                   GetFoldersAsync  —  возвращает   список  каталогов,   соответствующих запросу.

·                   OpenStreamForReadAsync —  открывает файл  для  чтения,  позволяет вернуть объект типа Stream, представленный в платформе .NET Framework уже давно. Этот и следующий метод можно использовать для стандартного для .NET взаимодействия с файлами.

·                   OpenStreamForWriteAsync —  аналогичный  предыдущему  методу,  но открывает файл для записи.

·                   OpenAsync — позволяет открыть файл и обойтись только механизмами Windows  Runtime,  предоставляя механизмы  работы  с  файлом  через интерфейсы.

Рассмотрим небольшой пример, демонстрирующий создание файла в корневом каталоге приложения.

public async void WriteFile()

{

StorageFolder current = ApplicationData.Current.LocalFolder;

StorageFile file = await current.CreateFileAsync( "hello.txt", CreationCollisionOption.ReplaceExisting);

IRandomAccessStream writeStream =

await file.OpenAsync(FileAccessMode.ReadWrite); IOutputStream outputStream = writeStream.GetOutputStreamAt(0);

DataWriter dataWriter = new DataWriter(outputStream); dataWriter.WriteString("hello");

await dataWriter.StoreAsync(); outputStream.FlushAsync();

}

Как   видите,  код   не   очень   простой   и   требует   регулярного   обращения к операторам await, да и сам метод был объявлен с модификатором async. Зато мы воспользовались только возможностями WinRT, не прибегая к механизмам

.N     ET, а чтобы не активировать механизмы работы с массивом байтов, применили вспомогательный класс DataWriter. Этот класс может использовать поток, чтобы облегчить процедуры чтения и записи в файл.

Процедура чтения данных из файла выглядит аналогично.

public async void ReadFile()

{

StorageFolder current = ApplicationData.Current.LocalFolder;

StorageFile sampleFile = await current.GetFileAsync("hello.txt"); IRandomAccessStream readStream =

await sampleFile.OpenAsync(FileAccessMode.Read);

IInputStream inputStream = readStream.GetInputStreamAt(0); DataReader dataReader = new DataReader(inputStream);

string myString = dataReader.ReadString((uint)readStream.Size);

}

Роуминг данных

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

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

Перейдем  к  классам,  которые  используются  для  создания   «переносимых» данных. Тут действуют уже известные механизмы. Вот  код, который позволяет получить ссылки на возможность создания объектов и файлов в облаке:

ApplicationDataContainer current=ApplicationData.Current.RoamingSettings; StorageFolder file=ApplicationData.Current.RoamingFolder;

Как видите, тут задействованы те же механизмы, что и при работе с локальным хранилищем. Впрочем, объект ApplicationData обладает двумя дополнительными свойствами, которые могут быть полезны при работе с этим типом данных:

·                   RoamingStorageQuota — показывает объем пространства,  доступного приложению;

·                   RoamingStorageUsage — показывает объем используемого пространства.

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

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

void InitHandlers()

{

ApplicationData.Current.DataChanged +=

new TypedEventHandler<ApplicationData, object>(DataChangeHandler);

}

void DataChangeHandler(ApplicationData appData, object o)

{

//обновление данных

}

Временные данные

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

StorageFolder folder=ApplicationData.Current.TemporaryFolder;

Далее работа происходит уже по шаблону.

Сергей Лутай, Сергей Байдачный, Windows 8 для C# разработчиков

По теме:

  • Комментарии