En un artículo anterior comentaba una de las posibilidades de almacenamiento de datos en aplicaciones Metro, los diccionarios clave-valor. Esto permitía, recordemos almacenar datos simples de una manera fácil y sencilla, aunque en ocasiones, querremos almacenar datos un poco más complejos. En este artículo se verá cómo almacenar objetos complejos sin tener que recurrir a una base de datos.
Pese a que la API de WinRT incluye todos los componentes necesarios para guardar los datos, hay bibliotecas de clases que nos facilitan mucho la vida. Concretamente esta, Generic Object Storage Helper for WinRT nos permite almacenar objetos y obtenerlos con pocas líneas de código.
Clase a guardar
Para este ejemplo, la clase que almacenaremos será una clase Person. Es requisito que las clases que se almacenen sean serializables, aunque no es necesario que incluyan el atributo. Existen limitaciones, claro, ya que por ejemplo, una ObservableCollection no se puede serializar, una imagen o un objeto de tipo URI tampoco. Además, tiene una ventaja muy interesante, y es que se pueden guardar listas con la misma facilidad, como se verá en el ejemplo.
public class Person { public string FirstName { get; set; } public string LastName { get; set; } public string PictureURL { get; set; } public Person Mother { get; set; } public Person Father { get; set; } }
Una vez obtenido el componente, se puede agregar el componente WinRtUtility.dll a la solución y ya se puede emplear.
Eligiendo el tipo de guardado y almacenando los datos
Podemos guardar los datos en tres espacios diferentes:
- Local: Los datos se almacenan en el espacio de la aplicación en el dispositivo. Se borran del dispositivo cuando se elimina la aplicación.
- Roaming: Los datos se almacenan en el espacio del usuario, de esta manera, si se accedes a la app desde otro ordenador donde esté iniciada la sesión con su cuenta Microsoft, se podrán obtener estos mismos datos.
- Temp: Almacenamiento temporal y volátil, datos que podamos desechar.
Para almacenar los datos, solamente son necesarias las dos líneas siguientes:
var objectStorageHelper = new ObjectStorageHelper<List>(StorageType.Local); objectStorageHelper.SaveAsync(personObject);
En la primera línea de código se establece el tipo de objeto a guardar así como el espacio en que se hará el guardado. En la segunda es en la que se realiza en guardado del objeto, de manera asíncrona siguiendo con los patrones de WinRT.
Estas líneas se pueden situar en el método OnSuspending, convenientemente situado para que su ejecución sea asíncrona, y situado en el fichero App.xaml.cs:
private async void OnSuspending(object sender, SuspendingEventArgs e) { var deferral = e.SuspendingOperation.GetDeferral(); //TODO: Save application state and stop any background activity var objectStorageHelper = new ObjectStorageHelper<List>(StorageType.Local); await objectStorageHelper.SaveAsync(Persons); deferral.Complete(); }
Carga de los datos
La carga de los datos es tan sencilla como el guardado, ya que se emplean dos líneas muy similares a las vistas anteriormente:
var objectStorageHelper = new ObjectStorageHelper<List>(StorageType.Local); Persons = await objectStorageHelper.LoadAsync();
Estas líneas se pueden situar en el método OnLoad, una vez más, modificado para que se ejecute de manera asíncrona:
protected async override void OnLaunched(LaunchActivatedEventArgs args) { Frame rootFrame = Window.Current.Content as Frame; // Do not repeat app initialization when the Window already has content, // just ensure that the window is active if (rootFrame == null) { // Create a Frame to act as the navigation context and navigate to the first page rootFrame = new Frame(); if (args.PreviousExecutionState != ApplicationExecutionState.Suspended) { var objectStorageHelper = new ObjectStorageHelper<List>(StorageType.Local); Persons = await objectStorageHelper.LoadAsync(); } // Place the frame in the current Window Window.Current.Content = rootFrame; } [...] // Ensure the current window is active Window.Current.Activate(); }
Conclusiones
En este artículo se ha visto que existe otra opción para el almacenamiento de estructuras de datos más complejas utilizando poco más que de dos líneas de código situadas en los eventos de carga y guardado de la aplicación.
Más información:
- Código de ejemplo en GitHub
- Página principal del componente: Generic Object Storage Helper for WinRT