In questa lezione analizzeremo la classe Application
e vedremo come viene gestito il ciclo di vita di un'applicazione Xamarin.Forms.
La classe Application
La classe Application
rappresenta la base di un'app cross-platform creata con Xamarin.Forms. Tale classe è contenuta nell'assembly Xamarin.Forms.Core, introdotto solo dalla versione 1.3 di Xamarin, e permette la definizione della prima pagina dell'app.
La classe si compone delle seguenti proprietà:
Proprietà | Descrizione |
---|---|
Current |
È una proprietà statica che contiene un riferimento all'oggetto dell'applicazione. |
MainPage |
Permette di settare la prima pagina dell'applicazione. |
Properties |
È un dizionario che estende l'interfaccia IDictionary<string, object> |
Resources |
È un altro dizionario di tipo ResourceDictionary , composto da coppie chiave-valore, dove le chiavi sono di tipo string e i valori sono di tipo object e rappresentano gli oggetti da memorizzare. Permette quindi di impostare e recuperare risorse per l'oggetto corrente. |
Tra queste proprietà, il dizionario Properties
ricopre un ruolo importante. Generalmente, i dati salvati al suo interno sono dati utilizzati in combinazione con i metodi del ciclo di vita dell'app definiti dalla classe Application
. Il dizionario permette di memorizzare solo dati di tipo primitivo (string
, int
, ecc) e, pertanto, qualsiasi tentativo di memorizzare dati di altri tipi, come List<string>
, falliscono. Il dizionario è salvato automaticamente sul dispositivo, rendendo i suoi dati disponibili nel momento in cui l'app torna ad essere visibile sullo schermo. Ciononostante, si può salvare il dizionario in modo proattivo usando il metodo SavePropertiesAsync()
, che lo salverà sul dispositivo in modo asincrono. Ciò risulta utile soprattutto a seguito di aggiornamenti importanti, evitando che eventi inattesi come il crash dell'app causino una mancata serializzazione dei dati.
Come anticipato, oltre alla definizione di queste proprietà, la classe Application
definisce ed espone anche i metodi per gestire il ciclo di vita dell'app, ossia: OnStart
, OnSleep
e OnResume
.
Esaminiamo ora il costruttore della classe App
del progetto HelloXamarin (Portatile).
public class App : Application
{
public App()
{
// The root page of your application
MainPage = new ContentPage
{
Content = new StackLayout
{
VerticalOptions = LayoutOptions.Center,
Children = {
new Label {
HorizontalTextAlignment = TextAlignment.Center,
Text = "Hello Xamarin!"
}
}
}
};
}
//...
}
Possiamo notare due aspetti fondamentali:
- la visibilità della classe è pubblica;
- la classe estende
Application
.
In questo modo la classe App
è visibile dai progetti di ogni piattaforma e può, attraverso il suo costruttore, inizializzare la proprietà MainPage
della classe Application
ad un oggetto ContentPage
di tipo Page
. Un oggetto Page
è l'analogo di una Activity
in Android, un ViewController
in iOS e una Page
in Windows Phone. Il codice autogenerato con la creazione del progetto mostrerà una Label
posizionata all'interno di uno StackLayout
e centrata al suo interno. Infine, grazie all'estensione della classe Application
, la classe App
ci permette di sovrascrivere e di definire il comportamento dell'app nei suoi diversi stati.
Ciclo di vita di un'app
Chi ha una conoscenza basilare dello sviluppo di app per piattaforme mobili sa che è possibile gestire il ciclo di vita di un'applicazione e delle relative pagine attraverso l'impiego di opportuni metodi. Questi ultimi permettono di modificare il comportamento dell'applicazione al verificarsi di determinati eventi, come l'arrivo di una chiamata o più semplicemente lo spegnimento dello schermo.
Gli stati in cui si può trovare un'app sono essenzialmente quattro, come riportato nella figura seguente.
La tabella seguente descrive il significato di ognuno degli stati appena illustrati.
Stato | Descrizione |
---|---|
Not Running | L'app non è stata ancora avviata |
Running | L'app è in esecuzion e visibile sullo schermo |
Pause/Inactive | L'app è interrotta da qualche evento esterno |
Backgrounded | L'app è in background (non visibile sullo schermo), ma sta comunque svolgendo delle operazioni |
Idle/Suspended | Se l'app non sta eseguendo alcuna operazione viene sospesa dal sistema operativo, che manterrà in vita il processo dell'app |
Le piattaforme Android, iOS e Windows Phone offrono una gestione articolata del ciclo di vita di una pagina, dalla sua creazione fino alla sua distruzione, come riportato nella figura seguente.
Al contrario, in Xamarin.Forms il ciclo di vita è definito attraverso i seguenti tre metodi:
Metodo | Descrizione |
---|---|
OnStart |
È chiamato quando l'app è inizializzata |
OnSleep |
È richiamato quando l'app viene sospesa ed è in background |
OnResume |
È chiamato quando l'app è nuovamente in foreground dopo essere stata messa in background |
È interessante notare che:
- la creazione di una pagina è effettuata attraverso il costruttore della pagina, come precedentemente mostrato nel costruttore
App()
; - non c'è un metodo di terminazione, che viene gestita a partire dal metodo
OnSleep
.
Il metodo OnSleep
è, infatti, l'ultimo metodo chiamato prima della fine dell'esecuzione dell'app, e dopo la sua chiamata non abbiamo alcuna notifica che ci avverta di un'imminente terminazione dell'app. Ad esempio: se l'utente sta spegnendo il telefono mentre la nostra app è in esecuzione, prima dello spegnimento verrà invocato il metodo OnSleep
a cui seguirà la terminazione. Ovviamente, questa regola non vale nei casi in cui l'app crasha a causa di comportamenti inaspettati.
Vediamo in azione il ciclo di vita della nostra app e modifichiamo il codice della classe App
come segue:
public class App : Application
{
public App()
{
//Lasciare inalterato il codice della pagina
}
protected override void OnStart()
{
Debug.WriteLine("HelloXamarin OnStart");
}
protected override void OnSleep()
{
Debug.WriteLine("HelloXamarin OnSleep");
}
protected override void OnResume()
{
Debug.WriteLine("HelloXamarin OnResume");
}
}
A questo punto, compiliamo e lanciamo l'app sull'emulatore di una delle piattaforme di destinazione della nostra soluzione, ad esempio Android, e facciamo attenzione a quanto verrà riportato nella finestra Output, alla voce Debug. Quando l'app è visibile sullo schermo, nella finestra di Output potremmo leggere HelloXamarin OnStart
a seguito della chiamata al metodo OnStart
. Cliccando invece sul tasto Back verrà invocato il metodo OnSleep
, l'app andrà in background e leggeremo HelloXamarin OnSleep
nella finestra di Output. Infine, riportando in foreground l'app, viene richiamato il metodo OnResume
e verrà visualizzata la scritta HelloXamarin OnResume
.
Di seguito è possibile vedere il risultato finale della finestra di Output.
In conclusione, per avere un'idea di come utilizzare la proprietà Properties
di Application
con i cambi di stato dell'app, modifichiamo il codice dei metodi OnSleep
e OnResume
come segue:
protected override void OnSleep()
{
Application.Current.Properties["test"] = "HTML.it";
Debug.WriteLine("HelloXamarin OnSleep");
}
protected override void OnResume()
{
if (Application.Current.Properties.ContainsKey("test"))
{
string test = Application.Current.Properties["test"] as string;
Debug.WriteLine(test);
// do something with id
}
Debug.WriteLine("HelloXamarin OnResume");
}
Eseguendo l'app sull'emulatore e riportandola in foreground potremo leggere nella finestra di Output la scritta “HTML.it”
e che tale valore è stato correttamente salvato all'interno del dizionario con la chiave “test”
per poter essere successivamente riutilizzato nel metodo OnResume
attraverso il Debug.Writeline()
.