Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Gestione dei file

Come gestire l'utilizzo di file all'interno di un progetto per implementare un'app mobile multipiattaforma con Xamarin.Forms.
Come gestire l'utilizzo di file all'interno di un progetto per implementare un'app mobile multipiattaforma con Xamarin.Forms.
Link copiato negli appunti

La gestione dei dati tramite file presenti nella memoria locale del dispositivo o integrati nell’app è una delle operazioni basilari da apprendere, in quanto permette allo sviluppatore di caricare dati, come una lista di ricette, o impostazioni personalizzate dell’utente e di realizzare funzioni per il salvataggio dei dati prodotti da una particolare operazione.

In questa lezione, si analizzeranno i passi necessari a caricare i dati integrati in un file XML e si vedrà come salvare e caricare i dati contenuti in un file di testo.

Integrazione di un file XML

Integrare un file XML (lo stesso vale anche per i file JSON o testuali) all’interno del progetto è un’operazione semplice. Creato un file di risorse da integrare nell’app, ad es. un file di ricette, è sufficiente spostare quest’ultimo nella radice del progetto HelloXamarin e, nella sezione Proprietà del file, impostare come azione di compilazione le voce Risorsa incorporata.

Figura 68. (click per ingrandire)


Una volta creata e incorporata la risorsa, occorre creare la nuova pagina che ospiterà la lista di oggetti da mostrare all’utente.

Creiamo, quindi, una nuova Form Xaml Page e chiamiamola XMLFileLoader. Nel codice XAML inseriamo all’interno della ContentPage la seguente ListView:

<ListView x:Name="list"/>

Nel code-behind e all’interno del costruttore della pagina, definiamo invece il processo di caricamento dei dati contenuti nel file XML. Definiamo inoltre un’altra classe per modellare le ricette che chiameremo Recipe, e la cui definizione è disponibile su GitHub.

var assembly = typeof(XMLFileLoaderExample).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream("HelloXamarin.recipes.xml");
ObservableCollection<Recipe> recipes;
using (var reader = new StreamReader(stream))
{
	var serializer = new XmlSerializer(typeof(ObservableCollection<Recipe>));
	recipes = (ObservableCollection<Recipe>)serializer.Deserialize(reader);
}

In particolare, per caricare i dati si stanno impiegando le Reflection API offerte da C#, che permettono di avere le informazioni sul tipo dichiarato nella classe Assembly. Ottenuta tale informazione, viene impiegato il metodo GetManifestResourceStream che permette di caricare la risorsa del manifesto specificato dalla variabile assembly, e descritta dalla stringa Namespace.NomeFile.Estensione (in questo caso HelloXamarin.recipes.xml). L’output sarà contenuto all’interno della variabile stream di tipo Stream che fornisce le funzioni di base per leggere e scrivere i dati organizzati come uno stream di byte. A questo punto, viene creato un nuovo oggetto XmlSerializer per poter deserializzare i dati contenuti nella variabile reader di tipo StreamReader, che rappresenta un’istanza del flusso di dati da leggere e contenuti in stream. L’output di questa operazione sarà salvato all’interno di una ObservableCollection e usato per popolare la ListView attraverso la sua proprietà ItemSource.

Di seguito è riportato il risultato finale.

Figura 69. (click per ingrandire)


È importante sottolineare che non è necessario che i file da caricare siano all’interno della root del progetto. Per una migliore organizzazione di quest’ultimo, conviene creare un’apposita cartella che conterrà il file, e l’unica modifica che andrà fatta nel code-behind sarà la stringa da passare al metodo GetManifestResourceStream, che risulterà essere Namespace.Cartella.NomeFile.Estensione.

Salvataggio e caricamento di un file di testo

Spesso è necessario salvare in appositi file di testo informazioni sulle impostazioni utente correnti o, più semplicemente, il contenuto di un’operazione o di una form. Poiché ogni sistema ha una struttura diversa per cartelle e per filesystem, Xamarin.Forms non offre un’unica soluzione che sia valida per tutte le piattaforme. Viene quindi impiegato il DependecyService per ottenere un riferimento all’implementazione nativa dei metodi definiti in un’apposita interfaccia.

Ciononostante, le librerie di Xamarin.iOS e Xamarin.Android includono una versione ad-hoc del .NET framework realizzata da Xamarin. Questa include un insieme di metodi all’interno della classe File del namespace System.IO che mappano le relative funzioni di I/O fornite da iOS e Android. Il problema si pone quindi con WindowsPhone and Windows 8.1 che usano una versione del .NET framework creata appositamente per loro.

Per ovviare a questo problema è quindi necessario definire l’interfaccia IFileManager all’interno del progetto HelloXamarin e le relative implementazioni FileManager_OSName (es. IFileManager_Android) per gli altri progetti.

Nell’interfaccia definiamo i seguenti tre metodi

Task SaveAsync(string filename, string text);
	Task<string> LoadAsync(string filename);
	bool FileExists(string filename);

che rispettivamente definiscono il metodo per salvare e caricare il file in modo asincrono e verificare che il file esista (e nel caso aggiornarlo con i nuovi dati).

Definiamo ora l’implementazione di questi metodi per Android e iOS come segue. Prima del namespace definiamo l’attributo:

[assembly: Dependency (typeof(IFileManager_OSName))]

necessario per il DependencyService. Inoltre, creiamo i metodi per salvare e caricare i dati:

public async Task SaveAsync (string filename, string text)
	{
		string path = CreatePathToFile (filename);
		using (StreamWriter sw = File.CreateText(path))
			await sw.WriteAsync(text);
	}
	public async Task<string> LoadAsync (string filename)
	{
		string path = CreatePathToFile (filename);
		using (StreamReader sr = File.OpenText(path))
			return await sr.ReadToEndAsync();
	}
	public bool FileExists(string filename)
	{
		return File.Exists(CreatePathToFile(filename));
	}

dove il metodo CreatePathToFile è privato ed è impiegato per definire il percorso del file:

string CreatePathToFile(string filename)
	{
		return Path.Combine(docsPath, filename);
	}

Inoltre, la variabile docsPath, che viene concatenata con il nome del file, viene determinata in modo diverso in base all’OS di destinazione. Per Android, ad esempio, viene invocato il metodo GetFolderPath della classe Environment (codice), mentre per iOS è impiegato il metodo GetUrls offerto dalla classe NSFileManager (codice).

Analogamente a quanto fatto per gli altri due OS, per WindowsPhone è necessario definire l’attributo

[assembly: Dependency(typeof(FileManager_WinApp))]

e implementare i tre metodi dell’interfaccia IFileManager usando le Windows.Storage API come qui riportato.

Le immagini seguenti mostrano le schermate dell’app prima del salvataggio dei dati inseriti e il caricamento del file salvato.

Figura 70. (click per ingrandire)


Figura 71. (click per ingrandire)


Ti consigliamo anche