"Realizzare applicazioni cross-platform con Xamarin e il pattern MVVM" by Matteo Pagani.
Xamarin è una delle tecnologie più interessanti quando si parla di sviluppo cross-platform, in quanto permette di riutilizzare le proprie conoscenze di C# per realizzare applicazioni con le stesse feature e performance di un'applicazione nativa. Usare Xamarin, però, non significa solamente poter realizzare app Android e iOS in C#, ma anche e soprattutto non dover scrivere e mantenere codebase completamente diverse. In questa sessione vedremo come poter massimizzare il riutilizzo di codice tra le diverse versioni della nostra applicazioni, aiutandoci con il pattern MVVM.
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Realizzare applicazioni cross-platform con Xamarin e il pattern MVVM
1. Realizzare applicazioni cross-platform
con Xamarin e il pattern MVVM
Matteo Pagani
Windows AppConsult Engineer
Microsoft
ROME 18-19 MARCH 2016
matteo.pagani@microsoft.com
@qmatteoq
7. IL PATTERN MODEL-VIEW-VIEWMODEL
• Aiuta lo sviluppatore a separare la logica dall’interfaccia
utente, migliorando la leggibilità, la testabilità e il design
del codice
• In ottica di sviluppo cross-platform, aiuta a massimizzare il
riutilizzo del codice su diverse piattaforme
• Il codice è suddiviso in tre layer differenti
• Nasce nel mondo delle tecnologie Microsoft, in quanto
sfrutta alcune delle principali feature dello XAML come il
data binding
9. DATA BINDING
• Permette di creare un canale per collegare due
proprietà di due oggetti: «source» e «target»
• La comunicazione può essere bidirezionale
• Nel pattern MVVM, il binding è utilizzato per
collegare i controlli nello XAML con le
proprietà di un ViewModel
<TextBlock Text="{Binding Path=Name}" />
10. DATACONTEXT
• Definisce il contesto a cui ogni controllo XAML può accedere
per sfruttare il binding.
• Il DataContext supporta l’ereditarietà.
• Nel pattern MVVM, il ViewModel viene definito come
DataContext dell’intera View: in questo modo, la View può
accedere a tutte le proprietà e comandi esposti dal
ViewModel.
<Page
x:Class="MVVMLight.Messages.Views.MainView"
DataContext="{Binding Source={StaticResource
MainViewModel}">
</Page>
11. INOTIFYPROPERTYCHANGED
• Come comportamento predefinito, una proprietà non è in
grado di far sapere al canale di binding che il suo valore è
cambiato
• Di conseguenza, i controlli non sono in grado di aggiornarsi in
automatico quando il valore della proprietà collegata cambia
• L’implementazione dell’interfaccia INotifyPropertyChanged
permette di gestire questo scenario
• Nel pattern MVVM, tutti i ViewModel implementano questa
interfaccia
12. INOTIFYPROPERTYCHANGED
Prima
public string Name { get; set; }
Dopo
private string name;
public string Name
{
get { return name; }
set
{
name = value;
NotifyOfPropertyChange(() => Name);
}
}
XAML
<TextBlock Text="{Binding Path=Name}" />
13. I COMMAND
• Solitamente le interazioni dell’utente sono gestite con gli event
handler, ovvero speciali metodi che sono collegati ad un
evento e che possono essere definiti solamente nel code
behind
• I command sono un modo per definire un’azione utilizzando
una proprietà e, di conseguenza, possono essere collegati da
un controllo tramite binding
• I command supportano la gestione dello stato (abilitato o
disabilitato), che si riflette automaticamente sulla UI del
controllo nell’interfaccia
14. I COMMAND
Codice
private ICommand _pinToStart;
public ICommand PinToStart
{
get
{
return _pinToStart
?? (_pinToStart = new RelayCommand(
() => taskService.PinToStart(CurrentItem),
() => canPin));
}
}
XAML
<Button Text="Pin to start" Command="{Binding Path=PinToStart}" />
16. PROBLEMA
• Il pattern MVVM si basa su concetti, come il
binding, che sono specifici del mondo XAML
• Ci serve uno strumento per poter gestire il
binding anche su piattaforme differenti da
Windows
• Esistono diverse librerie che permettono di
aggiungere le funzionalità che ci servono
17. MVVM LIGHT
• Libreria open source creata da Laurent Bugnion, Microsoft
MVP e membro della .NET Foundation
• Compatibile con numerose tecnologie: WPF, Silverlight,
Universal Windows Platform, Xamarin Android e iOS
• Offre gli strumenti base per implementare il pattern:
• Classe base per i ViewModel
• Classe base per i Command
• Dependency injection e messaggi
http://www.mvvmlight.net/
18. MVVM CROSS
• Libreria open source disponibile su GitHub
• E’ un framework completo che, oltre a mettere a disposizione
gli strumenti base per implementare il MVVM, offre
funzionalità per risolvere scenari specifici delle varie
piattaforme
• Alcuni esempi:
• Dependency injection
• Gestione del ciclo di vita della pagina
• Navigazione
http://mvvmcross.com/
20. SERVIZI
• Per poter riutilizzare non solo la business logic ma anche i
ViewModel in ottica cross-platform, questi non dovrebbero
contenere alcun riferimento ad API specifiche di una
piattaforma
• Un ViewModel dovrebbe solamente descrivere le operazioni
da effettuare e le interazioni con l’utente, demandando ad
altre classi l’implementazione vera e propria
• Benvenuti servizi
21. SERVIZI
public RelayCommand ShowDialogCommand
{
get
{
return new RelayCommand(async () =>
{
MessageDialog dialog = new MessageDialog("Hello world");
await dialog.ShowAsync();
});
}
}
Problema: questo command utilizza una API
specifica della Universal Windows Platform
22. SERVIZI
public interface IDialogService
{
Task ShowDialogAsync(string message);
}
I servizi vengono descritti da una interfaccia, che
descrive solamente le operazioni, e che viene
inclusa nel progetto condiviso
23. SERVIZI
L’implementazione vera e propria viene inclusa nel
progetto specifico per la piattaforma.
public class DialogService : IDialogService
{
public async Task ShowDialogAsync(string message)
{
MessageDialog dialog = new
MessageDialog(message);
await dialog.ShowAsync();
}
}
24. SERVIZI
Il ViewModel sfrutta l’interfaccia per invocare
l’operazione da eseguire:
public RelayCommand ShowDialogCommand
{
get
{
return new RelayCommand(async () =>
{
await _dialogService.ShowDialogAsync("Hello world");
});
}
}
25. PROBLEMA
Nell’approccio tradizionale, i servizi vengono
istanziati in fase di compilazione:
public MainViewModel MainViewModel
{
public MainViewModel()
{
DataService service = new DataService();
service.GetItems();
}
}
26. PROBLEMA
DataService service = new DataService();
service.GetItems();
DataService service = new DataService();
service.GetItems();
DataService service = new DataService();
service.GetItems();
DataService service = new DataService();
service.GetItems();
28. LA SOLUZIONE
public ViewModel1(IDataService dataService)
public ViewModel2(IDataService dataService)
public ViewModel3(IDataService dataService)
public ViewModelN(IDataService dataService)
IDataService
DataServiceTestDataService