Comments
Transcript
DispenseWP - Concetti chiave (2240416 byte)
+ Navigazione fra pagine Nicolò Sordoni + Window, Frame, Page In tutte le applicazioni Windows, sia le Store Apps, che le Phone Apps, esistono i seguenti concetti: Window (finestra), che non è altro che una porzione dello schermo. In Windows Phone, un’app ha una sola finestra, mentre le App Windows Store possono averne molteplici. Frame: Ogni Window può contenere un solo Frame, la cui dimensione è identica a quella della finestra. Il Frame viene creato all’avvio dell’applicazione, mostra la pagina corrente e mantiene in memoria lo stack contenente la cronologia di navigazione + Window, Frame, Page Page: La pagina è il concetto chiave delle nostre applicazioni, ed è quel componente che corrisponde ad una singola schermata della nostra app. Al suo interno possiamo definire l’interfaccia, la logica di interazione utente, ecc.. + Application Life Cycle In figura è mostrato il ciclo di vita delle applicazioni Windows Phone. Ogni app in esecuzione si trova in uno stato denominato Running; in qualsiasi momento si può verificare un evento (pressione del tasto Home, selezione di una notifica) che porta l’app ad essere sospesa. L’app passa innanzitutto nello stato Deactivated in cui il sistema esegue una serie di operazioni per ridurre l’impatto su memoria, batteria e CPU. + Application Life Cycle A questo punto l’app viene portata in uno stato denominato Dormant, in cui sono stati interrotti tutti i thread in background, sono state annullate le notifiche dei sensori ed è stato effettuato il dispose delle risorse non ritenute necessarie per un’applicazione non attiva. Lo stato dell’applicazione (Stack delle pagine, pagina attuale e dati contenuti al suo interno) viene però mantenuto, pertanto, riportandola in foreground, l’app rimarrà identica a quando l’abbiamo sospesa. Per tornare in background l’app passerà tramite lo stato Activated, in cui saranno ripristinate alcune delle funzionalità che erano state interrotte (es: sensori), sebbene non tutte. Ad esempio, i thread in background, dovranno essere riavviati da codice. + Application Life Cycle Sebbene il sistema gestisca per noi la persistenza dello stato della nostra app, non possiamo sempre far affidamento al 100% su tale meccanismo, dato che, come si nota dall’immagine che rappresenta il ciclo di vita, l’app può passare dallo stato Dormant a TombStoned. In tal caso lo stato della nostra app andrebbe perso, pertanto è buona norma memorizzare in maniera persistente lo stato, ogni volta che la nostra app viene posta in background. + Gestire la navigazione Come accennato, il componente responsabile di gestire la navigazione fra le varie pagine è il Frame, pertanto, per poter spostarci in una pagina abbiamo bisogno di utilizzare tale classe. All’interno di ogni pagina, abbiamo accesso diretto al frame che la contiene, grazie alla proprietà denominata, come possiamo intuire, Frame. Tale classe espone due overload del metodo Navigate, che ci permettono di navigare verso una differente pagina dell’app. La presenza di due differenti overload del metodo è dovuta all’eventuale necessità di passare un parametro alla nuova Page che andremo a visualizzare. + Frame.Navigate Frame.Navigate(Type sourcePageType); Frame.Navigate(Type sourcePageType, object parameter); Come possiamo notare, il metodo Navigate richiede come primo parametro un Type, cioè un tipo. Tale tipo deve essere quello della nuova pagina che vogliamo mostrare, pertanto la sintassi è la seguente: L’esempio precedente permette di navigare ad una nuova pagina, denominata SecondPage, a cui viene passato un oggetto come parametro. Tale oggetto può essere di qualsiasi tipo (Stringa, Intero,una qualunque classe definita dall’utente, ecc...). + metodo OnNavigateTo Ovviamente, dopo aver passato un parametro alla pagina che viene lanciata, è necessario che quest’ultima sia in grado di recuperarlo per poterlo utilizzare. A tale scopo ogni pagina espone un apposito metodo di callback, cioè OnNavigateTo. Tale metodo viene invocato nel momento in cui viene effettuata una navigazione verso la pagina corrente, prima che sia mostrata a video. Come si nota dall’esempio, tale metodo accetta come parametro un’istanza della classe NavigationEventArgs, che permette di accedere ai parametri ottenuti in input tramite la property Parameter. Questo è il punto ideale in cui ripristinare lo stato della nostra pagina, in caso di chiusura improvvisa. + metodo OnNavigatedFrom Oltre al metodo OnNavigatedTo, ne esiste un altro, speculare al primo, per gestire il caso in cui l’utente esca dalla pagina. Il parametro e ci permette di ottenere informazioni riguardo alla pagina alla quale stiamo per accedere. Tale metodo è il punto ideale in cui salvare lo stato e deallocare risorse non necessarie quando la pagina non è visualizzata, rimuovere eventuali Handler (come vedremo a breve), ecc.. + Tornare alla pagina precedente La classe Frame mantiene al suo interno la cronologia di navigazione, consentendo quindi in ogni momento di tornare alla pagina precedente. Il metodo da invocare è Frame.GoBack(). Dato che non sempre possiamo essere certi che esista una pagina precedente, è buona norma effettuare tale verifica, sfruttando la proprietà booleana Frame.CanGoBack. + Gestire la pressione del tasto back Una cosa a cui va prestata particolare attenzione, è l’utilizzo del tasto back. Il comportamento di default del sistema, nel momento in cui l’utente preme il tasto back, è quello di rimandarlo all’applicazione precedente. Pertanto la nostra app sarà posta in background per passare ad un’altra. Non sempre questo è il comportamento che desideriamo ottenere, dato che potremmo voler fare in modo che, premendo il tasto back, l’utente torni alla pagina precedente. + Tasto Back: Override a livello di App Sovrascrivere la pressione del tasto back a livello di App, ci permette di far si che ogni volta che l’utente preme back, non sarà il sistema a gestirlo, ma il metodo che avremo appositamente predisposto. In tal modo possiamo far sì che il comportamento di default sia quello di ritornare alla pagina precedente, gestendo il tutto in un unico punto del codice, senza doverlo ripetere per ogni pagina. Per ottenere tale risultato, è necessario sovrascrivere il comportamente di default del sistema. Il punto per farlo è all’avvio, quindi all’interno del costruttore della classe App. + Tasto Back: Override a livello di App Analizziamo il metodo che abbiamo definito per definire il nostro comportamento personalizzato. Innanzitutto utilizziamo la proprietà Window.Current.Content, per accedere innanzitutto alla finestra Corrente, che in WP è unica per ogni applicazione, e quindi al suo Content (cioè il Frame dell’app). Dopo aver verificato che tale frame esista, abbiamo gestito il ritorno alla Page precedente. + Tasto Back: Override a livello di Page L’utilizzo del back a livello di singola pagina è necessario in quei casi in cui abbiamo molteplici azioni che possono essere annullate tramite il tasto back. Il caso classico è quello in cui la nostra pagine presenta all’utente una finestra pop-up. In questo caso, potremmo voler fornire all’utente la possibilità di chiuderla tramite la pressione del back. Il codice nella seguente slide mostra come gestire tale situazione. Nel momento in cui l’utente accede alla pagina, è necessario aggiungere all’evento BackPressed, un apposito Handler. E’ importante rimuovere tale Handler in uscita dalla pagina, per evitare di invocare molteplici volte lo stesso metodo (in caso di accesso multiplo alla pagina) e di invocare il metodo anche dopo che la pagina non sarà più visualizzata. + Tasto Back: Override a livello di Page + Page CacheMode Nel momento in cui l’utente abbandona una determinata pagina, il sistema ha 2 possibilità: mantenerla in cache, oppure terminarla. Tale scelta dipenderà dall’attributo NavigationCacheMode, che avremo settato in tale Page: NavigationCacheMode.Disabled : ogni volta che la pagina viene visualizzata, viene creata una nuova istanza da capo. NavigationCacheMode.Enabled : il sistema mantiene in cache la pagina, ma può essere scartata se la dimensione della cache per il Frame corrente supera una determinata dimensione (determinata dalla proprietà Frame.CacheSize). NavigationCacheMode.Required : la pagina viene sempre e comunque mantenuta in cache. + Utilities: SuspensionManager e NavigationHelper Per aiutarci a preservare lo stato della nostra app, anche quando va in background, Microsoft ci mette a disposizione due classi di supporto: SuspensionManager : memorizza lo stato del nostro frame e ci permette di ripristinare lo stack delle pagine e di ritornare alla pagina corrente. NavigationHelper : ci permette di memorizzare informazioni riguardo alla pagina correntemente visualizzata, in modo da mantenere le informazioni anche se l’app viene terminata. + Utilities: SuspensionManager e NavigationHelper Tali classi vengono aggiunte in automatico quando inseriamo, all’interno del progetto, una nuova pagina di tipo BasicPage : Solution > Add > New Item.. e, dalla finestra che appare, selezioniamo Basic Page. Verremo informati che il sistema sta per aggiungere in automatico alcune nuove classi. Accettiamo e vedremo che comparirà una nuova sezione all’interno della nostra app, denominata Common. + SuspensionManager Il SuspensionManager, deve registrare al suo interno il Frame dell’applicazione corrente; il punto ideale per farlo è non appena è stato creato. Pertanto, per utilizzare il SuspensionManager, è sufficiente lavorare all’interno della classe App, dato che è in questo punto che vengono gestiti i principali eventi relativi al Frame. Il metodo onLaunched, viene invocato quando l’app viene lanciata per la prima volta. In questo metodo, che l’IDE ha già generato per noi con del codice all’interno, quello che l’app cerca di fare è recuperare il riferimento al Frame corrente; Se non riesce a recuperarlo, viene creata una nuova istanza. In questo punto andremo a registrare il Frame appena istanziato nel SuspensionManager e a cercare di ripristinare l’istanza precedente. + SuspensionManager L’esempio precedente mostra come applicare quanto detto nella precedente slide, mentre quello che segue, rappresenta il codice per recuperare lo stato precedentemente salvato. Il metodo onSuspending è invocato quando l’app viene messa in background + await e async Negli esempi precedenti è stato fatto uso di due parole chiave finora mai incontrate: await e async. Esse sono due nuove parole chiave, introdotte di recente da Microsoft, per gestire l’utilizzo di codice asincrono. async deve essere prefissa a tutte quelle chiamate che, dato che potrebbero richiedere molto tempo per essere eseguite, andrebbero lanciate in maniera asincrona. Usando la parola chiave async, viene invocato un metodo in maniera asincrona; nello stesso momento il metodo attualmente in esecuzione viene interrotto, ed il Thread ritorna disponibile per nuove operazioni; dato che solitamente si tratta del GUI Thread, in tal modo si impedisce che l’interfaccia rimanga bloccata. Non appena la chiamata asincrona sarà terminata, il controllo ritornerà al metodo precedente che completerà la sua esecuzione. async è una parola chiave che deve essere prefissa a tutti quei metodi che fanno uso di codice asincrono. + NavigationHelper Come accennato, esiste un componente che ci supporta nel mantenere persistente lo stato di una singola pagina. Per farlo dobbiamo dichiarare a livello d’istanza una nuova proprietà di tipo NavigationHelper, che andremo ad inizializzare nel costruttore della pagina. Oltre a questo è necessario invocare due metodi di Utility all’interno dei callback OnNavigatedTo e OnNavigatedFrom + NavigationHelper Questa classe offre due eventi, LoadState e SaveState, che vengono invocati rispettivamente quando la pagina viene caricata oppure chiusa. All’interno dei metodi associati a tali eventi, andremo a scrivere il codice che ci permetterà di preservare lo stato della pagina. + Controlli specifici dell’ambiente Nicolò Sordoni + L’ApplicationBar In Windows Phone si fa spesso uso della cosiddetta ApplicationBar, che non è altro che una barra, che viene visualizzata in basso, a fondo alla pagina, e permette un rapido accesso a determinate funzionalità dell’applicazione. I bottoni inseriti al suo interno sono divisi in due categorie: Primari, che possiedono un’icona che è sempre visualizzata, ed un testo, che viene mostrato solamente quando la barra viene espansa. Possono essere al massimo 4 Secondari, di default sono nascosti e diventano visibili all’espansione della barra. La barra di default mostra solamente le icone dei bottoni primari, ma è sempre presente un tasto che consente all’utente l’espansione della barra. + L’ApplicationBar + L’ApplicationBar Per inserire una barra all’interno di una pagina, è necessario utilizzare la proprietà Page.BottomAppBar. I bottoni vanno definiti all’interno di un nodo innestato al suo interno, denominato CommandBar. Il nodo CommandBar prevede al suo interno una suddivisione in due categorie: CommandBar.PrimaryCommands e CommandBar.SecondaryCommands, per definire rispettivamente bottoni primari e secondari. All’interno di tali sezioni andremo ad inserire i bottoni veri e propri, utilizzando il controllo AppBarButton. + AppBarButton Il controllo AppBarButton permette di definire un elemento che sarà mostrato all’interno dell’ApplicationBar. Le principali proprietà di tale controllo sono: Icon : Valida solamente nel caso di PrimaryCommand. Specifica quale icona sarà mostrata all’interno del cerchio per quel bottone. E’ possibile selezionarla fra un elenco di icone di default offerte da sistema, oppure utilizzare una propria icona personalizzata. Label : Specifica il testo che sarà associato al bottone e che sarà visualizzato in maniera differente a seconda di che tipo di bottone si tratti. Click : E’ un evento e permette di gestire il click sul bottone. + AppBarButton + Hub + Hub L’immagine alla slide precedente ci mostra un classico utilizzo di una pagina strutturata come Hub. La schermata è ovviamente più ampia della dimensione dello schermo di uno smartphone; questo perchè le varie sezioni (indicate come Panorama Panels), dovranno essere visualizzate una alla volta. L’utente potrà scorrerle semplicemente tramite uno swipe. La navigazione è circolare, quindi una volta arrivati all’ultima sezione, uno slide verso destra ci permetterà di tornare alla prima. La cosa che salta subito all’occhio in questo tipo di applicazione è l’immagine di sfondo. Questo tipo di applicazione presenta un’unica immagine come sfondo per tutte le sezioni, quindi scorrendo da un panel all’altro, scorrerà anche l’immagine. Spesso si fa uso di immagini circolari, in cui il margine destro coincide con quello sinistro, quindi non si ha mai un taglio netto, neanche quando si passa dall’ultimo Panel al primo. Notiamo come anche il titolo sia distribuito su più sezioni, per sottolineare la presenza di ulteriori informazioni. + Hub Ognuna delle sezioni di questo pattern non è vincolata in alcun modo alle altre, ma è libera di mostrare qualsiasi tipo di informazione. Ovviamente è necessario che le varie viste abbiano comunque un target comune, altrimenti non avrebbero motivo di trovarsi nella stessa pagina. Questo tipo di pattern viene utilizzato molto per realizzare le schermate iniziali delle applicazioni, fungendo per certi versi da vetrina. In questo modo è possibile presentare all’utente le funzionalità principali e più interessanti in una maniera accattivante. Ciò che è importante tenere a mente è che questo pattern non è stato concepito come contenitore di dati, ma esclusivamente come punto di accesso a ulteriori funzionalità. E’ pertanto sconsigliato, sia dal punto di vista dell’esperienza utente, che delle performance, inserire troppe informazioni in un Hub. Microsoft suggerisce di non usare più di 5 sezioni. + Pivot + Pivot Il pivot, come il panorama, è suddiviso in più sezioni, che possono essere navigate tramite swipe. Anche in questo caso si ha circolarità di navigazione. Il pivot mostra una sezione alla volta, ma in alto possiamo notare la presenza dei titoli di molteplici sezioni (2 o 3). Questo per notificare la presenza di ulteriori viste oltre a quella corrente. Il titolo della sezione attualmente selezionata avrà una colorazione più marcata e sarà il primo della lista. La differenza principale con l’Hub, è la presenza di un legame relativamente forte fra le informazioni contenute nelle singole pagine. Questo pattern è solitamente utilizzato per mostrare la stessa tipologia di informazione, ma filtrata o mostrata in maniere differenti, oppure per mostrare informazioni diverse, ma comunque legate allo stesso soggetto. + Pivot : implementazione Per inserire un Pivot all’interno della nostra applicazione, è sufficiente utilizzare il controllo denominato, ovviamente, Pivot. Al suo interno possiamo inserire le sezioni tramite il controllo PivotItem. Quest’ultimo possiede una proprietà Header, che imposteremo per definire il titolo della sezione, mentre per definire quale sarà il suo contenuto è sufficiente inserire al suo interno dei controlli XAML. + Hub: implementazione L’utilizzo dell’Hub è lievemente più complicato rispetto al Pivot, dato che richiede un ulteriore passaggio. Dopo aver inserito il controllo Hub, è necessario introdurre al suo interno una serie di HubSection. All’interno di tali nodi non va inserito direttamente il layout della sezione, ma è necessario inteodurre un ulteriore nodo, denominato DataTemplate. All’interno di tale nodo inseriremo le specifiche per la visualizzazione. Per impostare l’immagine è necessario inserire un Brush all’interno della proprietà Background.