SlideShare a Scribd company logo
Xamarin.Forms Performance Tips & Tricks
Francesco Bonacci
ROME 24-25 MARCH 2017
@xamarinhq lo adora, lo sviluppatore lo
teme e il cliente lo odia...
Forse un pò mal giudicato.. È davvero
sempre colpa del framework?
Il dilemma degli ultimi tempi assieme a
PCL vs. SP
O odia voi?
Vediamo come risolvere!
1. Native vs. Forms
2. XamlC
3. View
4. Layout
5. Binding
6. UI Thread
7. Forms Embedding
iOS C# UI Windows C# UIAndroid C# UI
Shared C# Mobile
 C# Wrapper per l’accesso
ad API native
 Riutilizzo codebase comune
 Performance ~ Approccio Silo
 Progetto della UI dipendente da tool e
modalità native
Shared C# Mobile
Xamarin.Forms
 Xaml/C# UI codebase
 API di Sistema astratte
 Data Binding e MVVM
 Performance < Xamarin.Native
 Xamarin.Forms non è adatto a tutti i tipi di app
 OK per applicazioni di utilità o data-entry
x Non ideale se l’obiettivo finale è produrre effetti grafici sfavillanti
 Primo approccio affrontato per chi viene dal mondo WPF, WinRT, UWP
ecc.  Occorrerebbe prima conoscere quello che c’è sotto...
 Spesso usato da team per la prima fase di prototipaggio
dell’applicazione  Poi se il cliente non è contento si passa a Native…
MA se ci facciamo bastare quello che offre Xamarin.Forms?
Xamarin.Forms non è da sottovalutare:
 Si possono creare UI accattivanti e anche complesse
github.com/xamarinhq/app-evolve
Xamarin.Forms non è da sottovalutare:
 Si possono creare UI accattivanti e anche complesse
 Si evita di replicare il codice della UI
github.com/xamarinhq/app-evolve
iOS Android UWP
*Statistiche prese dall’app
Xamarin Evolve 2016
Codice
cross-platform
Xamarin.Forms non è da sopravvalutare:
 Occorre tener conto dell’ulteriore Layer di astrazione
 E’ un framework ancora giovane
 Lo XAML non è lo stesso di UWP…
 Non si può pensare di sviluppare una pagina Forms senza sapere quello
che c’è sotto!
 A volte l’unica cosa da fare è utilizzare bit nativi - aka Custom Renderer
ed Effect
Nel progettare la UI con Xamarin.Forms bisogna:
 Utilizzare i controlli più adatti per lo scenario in mente
 Non eccedere con la densità dell’albero visuale (Visual Tree)
 Sfruttare a proprio vantaggio le funzionalità (nascoste) di Xamarin
 L’HW dell’utente medio è pessimo  Prendere come riferimento la
fascia medio-bassa
 Avere buon senso…
… E seguire le prossime linee guida
XamlCompilationOptions
Compile Skip
Compilazione AOT (in CIL) Compilazione JIT
Se si utilizza XAML per la UI si può specificare la modalità di compilazione:
 Velocizza il caricamento degli
elementi visuali
 Riduce la dimensione del
pacchetto finale
 Tempi di compilazione più lunghi
 Valore di default per garantire
retro compatibilità
 Nessuna validazione dello XAML
compile-time
A livello di Assembly
 E’ buona prassi
farlo nel file
AssemblyInfo.cs
A livello di Pagina
bit.ly/2nQ5JZw
0
100
200
300
400
500
600
700
800
Android
Initialization Time (Avg)
Skip Compile
 Time profiled on Page
InitializeComponent()
 Average calculated on a
population of size 20
 HW: LG Nexus 5X with
Android 7.1 Nougat
ms
bit.ly/2nQ5JZw
0
100
200
300
400
500
600
700
800
UWP
Initialization Time (Avg)
Skip Compile
ms  Time profiled on Page
InitializeComponent()
 Average calculated on a
population of size 20
 HW: Lumia 640 LTE with
Build 10.0.14393.0
bit.ly/2nQ5JZw
0
20
40
60
80
100
120
iOS
Initialization Time (Avg)
Skip Compile
 Time profiled on Page
InitializeComponent()
 Average calculated on a
population of size 20
 HW: iPhone Simulator 7
Plus with iOS 10.2
ms
Una View in Forms rappresenta un nodo
nell’albero della pagina (Visual Tree) avente
proprietà visuali ed un comportamento
Una View in Forms rappresenta un nodo
nell’albero della pagina (Visual Tree) avente
proprietà visuali ed un comportamento
Rappresenta l’elemento di più basso
livello, assieme a Page, nella gerarchia di
ereditarietà di Xamarin.Forms
Esempi: Label, Editor, Button, Image…
La creazione di una View in Xamarin.Forms è suddivisa in due fasi:
Inflating
Istanziamento della View
Rendering
Aggiunta all’albero visuale
(Automatica in Xaml)public MainPage()
{
var stackLayout = new StackLayout();
stackLayout.Children.Add(new Label() {
Text = "Hello Codemotion!"
});
//...
}
public MainPage()
{
//...
Content = stackLayout;
}
 Evitare di usare trasparenza e opacità, specialmente in Android
 Preferire le Bindable Property TranslationX e TranslationY, piuttosto
che Padding e Margin, per eseguire riordinamenti post-layout
 Non specificare i valori di default delle proprietà visuali, specialmente
VerticalOptions e HorizontalOptions  Vengono scatenati cicli di
misura superflui
Per far seguire porzioni di testo con caratteristiche diverse preferire la
Bindable Property FormattedText di Label
<StackLayout Orientation="Horizontal">
<Label Text="Hello"
TextColor="Blue"/>
<Label Text="Codemotion!"
TextColor="Orange"/>
</StackLayout>
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="Hello "
ForegroundColor="Blue"/>
<Span Text="Codemotion!"
ForegroundColor="Orange" />
</FormattedString>
</Label.FormattedText>
</Label>
Le Bindable Property VerticalTextAlignment e HorizontalTextAlignment di
tipo TextAlignment sono ottimizzate per posizionare elementi visuali di
tipo Label
<Label Text="Hello Codemotion!"
VerticalOptions="Center"
HorizontalOptions="Center"/>
<Label Text="Hello Codemotion!"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Center"/>
<Image Source="resource.png"/>
<Image>
<Image.Source>
<FileImageSource File="file.png"/>
</Image.Source>
</Image>
Image.Source = ImageSource.
FromResource("resource.png");
Image.Source = ImageSource.
FromFile("file.png");
Preferire come ImageSource un immagine salvata nel File System
piuttosto che un File di Risorse
 Disabilitare Opacità 
 Problematiche in Android  e.g. JPG CMYK non supportati
 Da preferire downscaling e manipolazione server-side
<Image IsOpaque="False"/>
Eventualmente non
reinventare la ruota…
<ffimageloading:CachedImage LoadingPlaceholder="loading.png"
DownsampleToViewSize="True">
<ffimageloading:CachedImage.Transformations>
<ffimageloading:GrayscaleTransformation />
</ffimageloading:CachedImage.Transformations>
</ffimageloading:CachedImage>
github.com/luberda-molinet/FFImageLoading
Problematiche fino all’introduzione di una strategia di caching delle celle in
Xamarin.Forms 2.0
public class CustomListView : ListView
{
public CustomListView(ListViewCachingStrategy cachingStrategy) :
base(cachingStrategy) { //... }
}
<ListView CachingStrategy="RecycleElement"/>
var listView = new ListView(
ListViewCachingStrategy.RecycleElement);
Se controllo custom, esporre il costruttore della classe base
ListViewCachingStrategy
RecycleElement RetainElement
 La ListView mantiene un pool di
celle di dimensione pari alla
finestra visuale di scorrimento
(Cell Recycling)
 Ideale se il layout delle celle è
statico  Ad esempio se non si
utilizzano DataTemplateSelector
 Valore di default per garantire
retrocompatibilità
 La ListView genera una nuova
cella per ogni elemento della
lista (Cell Retention)
 Ideale se si utilizza un alto
numero di Binding
 Preferire IList<T> anziché IEnumerable<T> come sorgente ItemsSource
della ListView  Supporto ad accesso casuale
 Se si utilizza RecycleElement come strategia di Caching, rimuovere i
Binding della cella ed aggiornarli nell’handler OnBindingContextChanged
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
var item = BindingContext as ItemViewModel;
if (item != null)
{
item.Title = TitleLabel.Text;
}
}
<ScrollView>
<StackLayout>
<Label Text="Header" />
<ListView />
<Label Text="Footer" />
</StackLayout>
</ScrollView>
Per abilitare lo scrolling all’interno di pagine contenenti ListView
utilizzare i DataTemplate
<ListView Header="Header" Footer="Footer">
<ListView.HeaderTemplate>
<DataTemplate>
<Label Text="{Binding .}" />
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.FooterTemplate>
<DataTemplate>
<Label Text="{Binding .}" />
</DataTemplate>
</ListView.FooterTemplate>
</ListView>
HeaderTemplate e FooterTemplate
Un Layout in Forms rappresenta un nodo
nell’albero della pagina avente proprietà
visuali e un comportamento
È responsabile della posizione e dimensione
dei suoi nodi figlio
Eredita da VisualElement, Element ma non
da View
Esempi: Grid, StackLayout, AbsoluteLayout...
Un Layout in Forms rappresenta un nodo
nell’albero della pagina avente proprietà
visuali e un comportamento
È responsabile della posizione e dimensione
dei suoi nodi figlio
La creazione e l’aggiornamento di un Layout in Xamarin.Forms attraversano
due fasi (o cicli):
Invalidation Cycle (IC)
 Dal nodo di più basso livello, si
notifica ricorsivamente il nodo padre
dell’invalidazione (aggiornamento)
del proprio Layout
 Ha termine una volta raggiunto il
nodo radice (e.g. Page) o se il padre
decide di ignorare l’invalidazione
Layout Cycle (LC)
 A seguito dell’invalidazione e
procedendo top-bottom, la pagina
riorganizza il layout degli elementi
etichettati come "invalidati"
 La riorganizzazione termina con
l’ultimo elemento invalidato
No Si
public enum InvalidationTrigger {
Undefined = 0,
MeasureChanged = 1 << 0,
HorizontalOptionsChanged = 1 << 1,
VerticalOptionsChanged = 1 << 2,
SizeRequestChanged = 1 << 3,
RendererReady = 1 << 4,
MarginChanged = 1 << 5
}
L’invalidazione di un Layout può essere
causata da diversi fattori  Indicati
dall’enumerativo InvalidationTrigger
Ogni Layout può decidere di gestire a
suo modo l’invalidazione di un figlio,
eventualmente interrompendo il ciclo di
invalidazione
Lo sviluppatore può sfruttare
l’interruzione di Layout di sistema
(anche implementando il proprio)
per guadagnare ms sull’IC
Si No
foreach child in layout.Children
 Il Layout Cycle termina con il Layout() dell’ultimo elemento invalidato
 L’implementazione dei metodi Measure e Layout è demandata ai
Custom Renderer specifici per il Layout
 Diversamente dall’Invalidation Cycle, non è possibile controllare il
ciclo di Layout
 Se si definisce una View da codice, è bene aggiungere la View
contenitore all’albero visuale solo quando si è finito di manipolare la
struttura delle sue subview  Altrimenti ulteriori cicli di Misure
 Aggiungere View al VT nel costruttore e non in OnAppering() 
Altrimenti ulteriori cicli di Invalidazione
 Non utilizzare ForceLayout()
 Non sostituire ListView con ScrollView+StackLayout  Nessuna
virtualizzazione delle subview
Grid organizza il layout dei suoi figli in celle individuate da Righe e Colonne
 Permette di creare Layout composti senza eccessivo
nesting
 Occorre prestare attenzione all’utilizzo di Righe e
Colonne per il dimensionamento
L’invalidazione di una delle View
figlie provoca l’invalidazione a
catena del Visual Tree fino a Grid
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Text="Hello Codemotion!"/>
<Label Grid.Row="1"
Text="Hello Codemotion!"/>
</Grid>
E se l’elemento invalidato è un
nodo foglia e nessun Layout
interrompe il ciclo?!
Grid organizza il layout dei suoi figli in celle individuate da Righe e Colonne
Poiché lo spazio messo a
disposizione degli elementi figlio è
proporzionale alla superview ma
indipendente dalle subview, Grid
ignora eventuali notifiche di
invalidazione dai suoi figli
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Text="Hello Codemotion!"/>
<Label Grid.Row="1"
Text="Hello Codemotion!"/>
</Grid>
Grid organizza il layout dei suoi figli in celle individuate da Righe e Colonne
Poiché lo spazio messo a
disposizione degli elementi figlio è
fissato staticamente, Grid ignora
eventuali notifiche di invalidazione
dai suoi figli
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Label Text="Hello Codemotion!"/>
<Label Grid.Row="1"
Text="Hello Codemotion!"/>
</Grid>
Grid organizza il layout dei suoi figli in celle individuate da Righe e Colonne
Utilizzare le Bindable Property RowSpacing e ColumnSpacing per controllare la
distanza tra Righe e Colonne
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="10"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Label Text="Hello Codemotion!"/>
<Label Grid.Row="1"
Text="Hello Codemotion!"/>
</Grid>
<Grid RowSpacing="10">
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Label Text="Hello Codemotion!"/>
<Label Grid.Row="1"
Text="Hello Codemotion!"/>
</Grid>
StackLayout organizza il layout dei suoi figli su di un’unica riga o colonna
 Ideale per creare Layout semplici impilando
sequenzialmente controlli
 Può portare ad un eccessivo nesting del VT
L’invalidazione di una delle View figlie
provoca l’invalidazione a catena del
Visual Tree fino a StackLayout
E se l’elemento invalidato è un
nodo foglia e nessun Layout
interrompe il ciclo?!
<StackLayout>
<Label Text="Hello Codemotion!"/>
<Label Text="Hello Codemotion!"/>
</StackLayout>
StackLayout organizza il layout dei suoi figli su di un’unica riga o colonna
Grid - Auto Sizing
Golden Rule
“ Don’t use a StackLayout to host a single child
Don’t use a Grid when a StackLayout would do
Don’t use multiple StackLayout when a Grid would do ”
Jason Smith at Evolve 2016
AbsoluteLayout permette di posizionare e dimensionare controlli figlio in
maniera assoluta utilizzando valori statici o proporzionali
 Ideale se il Layout è facilmente descrivibile e
indipendente dalla posizione di altre view
 Massimo delle Performance
 Poco Leggibile
L’invalidazione di una delle View figlie provoca l’invalidazione a catena del
Visual Tree fino ad AbsoluteLayout
AbsoluteLayout permette di posizionare e dimensionare controlli figlio in
maniera assoluta utilizzando valori statici o proporzionali
<AbsoluteLayout>
<Label Text="Hello Codemotion!"
AbsoluteLayout.LayoutBounds=".02,.01"
AbsoluteLayout.LayoutFlags="PositionProportional"/>
<Label Text="Hello Codemotion!"
AbsoluteLayout.LayoutBounds=".02,.05"
AbsoluteLayout.LayoutFlags="PositionProportional"/>
</AbsoluteLayout>
Poiché lo spazio messo a disposizione degli elementi figlio è fissato
staticamente, AbsoluteLayout ignora notifiche di invalidazione dai suoi figli
AbsoluteLayout permette di posizionare e dimensionare controlli figlio in
maniera assoluta utilizzando valori statici o proporzionali
<AbsoluteLayout>
<Label Text="Hello Codemotion!"
AbsoluteLayout.LayoutBounds="10,10,200,100" />
<Label Text="Hello Codemotion!"
AbsoluteLayout.LayoutBounds="10,30,200,100" />
</AbsoluteLayout>
 Ideale se la dimensione o la posizione dei controlli
del Layout è strettamente correlata
 Peggiori Performance
RelativeLayout permette di posizionare e dimensionare controlli figlio
relativamente alla View contenitore o ad altre view del layout
L’invalidazione di una delle View figlie provoca l’invalidazione del Visual
Tree fino a RelativeLayout
<RelativeLayout>
<Label x:Name="Label1" Text="Hello Codemotion!" />
<Label Text="Hello Codemotion!"
RelativeLayout.YConstraint=
"{ConstraintExpression Type=RelativeToView,
Property=Y,
ElementName=Label1,
Constant=20}" />
</RelativeLayout>
RelativeLayout permette di posizionare e dimensionare controlli figlio
relativamente alla View contenitore o ad altre view del layout
ScrollView aggiunge la funzionalità di scrolling alla sua subview
 Non innestare più ScrollView  Comportamenti
poco intuitivi
 Non innestare ListView  Rompe la virtualizzazione
Demo
GitHub Repo: bit.ly/2nVm2Ei
N.B. Repo strutturata in submodule
1. Clonare la repo principale (fork di Xamarin.Forms):
2. Checkout sul branch layout:
3. Clonare la subrepo:
4. Avviare il progetto AppDemo4 dalla repo principale
bit.ly/2nzxf1B
bit.ly/2ndfZhE
bit.ly/2nzypdt
Il Binding è una funzionalità integrata nel framework Xamarin.Forms
 Consente di creare associazioni loosely-coupled tra una proprietà
Sorgente e una proprietà Target
 Utilizzato assieme al pattern MVVM, permette di slegare Modello e View
frapponendo uno strato di ViewModel
Source
Qualsiasi Object
Target
BindableObject
BindablePropertyProprietà Pubblica Binding
TwoWay
OneWayToSource
OneWay
Binding
1 Scatenata notifica PropertyChange
2 Il Binding legge il valore
della nuova proprietà
3 Il Binding aggiorna la proprietà Target
p.Name = "Jerry";
public abstract class BindableObject : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
//...
}
Golden Rule
“Don’t bind things that can be set statically” Jason Smith at Evolve 2016
public abstract class BindableObject : INotifyPropertyChanged {
//...
void SetValueActual(BindableProperty property, BindablePropertyContext context, object
value, bool currentlyApplying, SetValueFlags attributes, bool silent);
void SetValueCore(BindableProperty property, object value, SetValueFlags attributes,
SetValuePrivateFlags privateAttributes);
}
Rendere la UI responsive:
 Non interrompere la catena async/await
bloccando il Thread principale su un operazione
I/O Bound
 Non eseguire Task altamente computazionali sullo
UI Thread
Obiettivo: 60 fps ad ogni animazione e transizione!
Rendere la UI responsive:
 Utilizzare il pattern asincrono per restituire subito
il controllo alla Message Pump (UI Thread) -
eventualmente ConfigureAwait(false)
 Schedulare CPU-Bound Task su Thread secondari
(Background Thread)
Obiettivo: 60 fps ad ogni animazione e transizione!
Task.Run() Task.Factory.StartNew()
UI
Thread
DownloadAsync
ReadingfromURL
GetString
LoadData
I/O
È possibile trarre vantaggio dalla separazione tra Inflating e Rendering
delegando l’esecuzione della prima fase ad un Thread secondario
Task<StackLayout> InflateOnBackgroundThread()
{
return Task.Factory.StartNew(() =>
{
var stackLayout = new StackLayout();
stackLayout.Children.Add(new Label
{
Text = "Hello Codemotion"
});
return stackLayout;
});
}
public MainPage()
{
InflateOnBackgroundThread()
//...
}
Nel caso l’Inflating venga eseguito in un Thread secondario:
 Non è possibile da BT modificare il Visual Tree
 Per farlo, occorre restituire il controllo al Thread chiamante, in questo
caso lo UI Thread
InvalidOperationException
public MainPage()
{
var uiTaskScheduler =
TaskScheduler.FromCurrentSynchronizationContext();
InflateOnBackgroundThread()
.ContinueWith(
task => AddToVisualTree(task.Result),
uiTaskScheduler);
}
Catturare il contesto di
sincronizzazione
corrente
Eseguire l’unmarshalling e
l’aggiunta al VT nello
UI Thread
Demo
GitHub Repo: bit.ly/2nRLOcS
Un punto debole di un’applicazione Xamarin.Forms è rappresentato dai
suoi tempi di avvio
Il principale responsabile è l’avvio del sistema di Rendering ~ 1s
0
500
1000
1500
2000
2500
3000
3500
Android
Initialization Time (Avg)
Xamarin.Native Xamarin.Forms
 Time profiled from App
Start to View Rendering
 Average calculated on a
population of size 20
 HW: LG Nexus 5X with
Android 7.1 Nougat
ms
0
200
400
600
800
1000
1200
1400
Android
OnCreate Time (Avg)
Xamarin.Native Xamarin.Forms
 Time profiled on
MainActivity OnCreate()
 Average calculated on a
population of size 20
 HW: LG Nexus 5X with
Android 7.1 Nougat
ms
0
1000
2000
3000
4000
5000
6000
7000
8000
9000
UWP
Initialization Time (Avg)
Xamarin.Native Xamarin.Forms
 Time profiled from App
Start to View Rendering
 Average calculated on a
population of size 20
 HW: Lumia 640 LTE with
Build 10.0.14393.0
ms
0
1000
2000
3000
4000
5000
6000
7000
UWP
OnCreate Time (Avg)
Xamarin.Native Xamarin.Forms
 Time profiled on App
OnLaunched()
 Average calculated on a
population of size 20
 HW: Lumia 640 LTE with
Build 10.0.14393.0
ms
0
500
1000
1500
2000
2500
3000
3500
4000
4500
5000
iOS
Initialization Time (Avg)
Xamarin.Native Xamarin.Forms
 Time profiled from App
Start to View Rendering
 Average calculated on a
population of size 20
 HW: iPhone Simulator 7
Plus with iOS 10.2
ms
0
200
400
600
800
1000
1200
1400
iOS
FinishedLaunching Time
(Avg)
Xamarin.Native Xamarin.Forms
 Time profiled on
AppDelegate
FinishedLaunching()
 Average calculated on a
population of size 20
 HW: iPhone Simulator 7
Plus with iOS 10.2
ms
Per risolvere questo problema si può pensare di trarre vantaggio dei tempi
di caricamento minori di Xamarin.Native
1. Si avvia l’app seguendo le modalità native e non si inizializza il sistema
di rendering di Forms
2. Si utilizza una View nativa come prima Pagina
3. Si avvia l’engine di Xamarin.Forms in un secondo momento (e.g.
tramite callback, timer, metodi asincroni…)
4. Si utilizzano da qui in poi le API di Forms - eventualmente solo quando
servono (e.g. View semplici come Settings, Login, ecc.)
Tutto molto bello ma ancora non supportato da Xamarin.Native
Xamarin.Forms Feature Roadmap
Ma…
public class FormsActivity : FormsAppCompatActivity {
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
var pageName = Intent.Extras.GetString("PageType");
var fullName = typeof(FormsApp).Namespace + ".Pages." + pageName;
var pageType = typeof(FormsApp).Assembly.GetType(fullName);
if (!IsFormsInitialized) {
global::Xamarin.Forms.Forms.Init(this, bundle);
IsFormsInitialized = true;
}
LoadApplication(new FormsApp(pageType));
}
}
Possiamo utilizzare le API attuali per caricare pagine Xamarin.Forms in
progetti Xamarin.Native – per View e Layout bisogna però aspettare…
var intent = new Intent(this,
typeof(FormsActivity));
intent.PutExtra("PageType", "SettingsPage");
StartActivity(intent); public FormsApp(Type pageType) {
MainPage =
(Page)Activator.
CreateInstance(pageType);
}
Dopodiché, si avvia normalmente l’Activity con le API di Xamarin.Android
passando l’indicazione della pagina Forms nel Bundle Extra
public class FormsWrapperPage : WindowsPage
{
private readonly FormsApp _formsApp;
public FormsWrapperPage()
{
this.InitializeComponent();
LoadApplication(_formsApp = new FormsApp());
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
_formsApp.SetMainPage(e.Parameter as Type);
}
}
Possiamo utilizzare le API attuali per caricare pagine Xamarin.Forms in
progetti Xamarin.Native – per View e Layout bisogna però aspettare…
Dopodiché, si utilizzano normalmente le API di Navigazione di UWP
passando come parametro di navigazione il tipo della Pagina Forms di
destinazione
public SetMainPage(Type pageType) {
MainPage =
(Page)Activator.
CreateInstance(pageType);
}
this.Frame.Navigate(
typeof(FormsWrapperPage),
typeof(SettingsPage));
Possiamo utilizzare le API attuali per caricare pagine Xamarin.Forms in
progetti Xamarin.Native – per View e Layout bisogna però aspettare…
Nel caso di iOS la classe Xamarin.Forms.PageExtensions espone il metodo di
estensione CreateViewController  Dopodichè, si può presentare il
ViewController utilizzando le API di Xamarin.iOS
public static Page GetPage<T>() where T : Page
{
return Activator.CreateInstance<T>();
}
var settingsViewControler = FormsApp.GetPage<SettingsPage>().CreateViewController();
await this.PresentViewControllerAsync(settingsViewControler, true);
Demo
GitHub Repo: bit.ly/2mkO5kq
Xamarin.Forms Performance Tips & Tricks - Francesco Bonacci - Codemotion Rome 2017
Xamarin.Forms Performance Tips & Tricks - Francesco Bonacci - Codemotion Rome 2017
Xamarin.Forms Performance Tips & Tricks - Francesco Bonacci - Codemotion Rome 2017

More Related Content

What's hot

Actions on Google e Alexa skills per .NET lovers
Actions on Google e Alexa skills per .NET loversActions on Google e Alexa skills per .NET lovers
Actions on Google e Alexa skills per .NET lovers
Lorenzo Giudici
 
DotNetCampus - Continuous Integration con Sql Server
DotNetCampus - Continuous Integration con Sql ServerDotNetCampus - Continuous Integration con Sql Server
DotNetCampus - Continuous Integration con Sql Server
Alessandro Alpi
 
Del furia signalr-to-the-max
Del furia   signalr-to-the-maxDel furia   signalr-to-the-max
Del furia signalr-to-the-maxDotNetCampus
 
Javascript task automation
Javascript task automationJavascript task automation
Javascript task automation
Antonio Liccardi
 
Introduzione a Service Fabric e Actor Model
Introduzione a Service Fabric e Actor ModelIntroduzione a Service Fabric e Actor Model
Introduzione a Service Fabric e Actor Model
Andrea Tosato
 
Training Signal Webtrends
Training Signal WebtrendsTraining Signal Webtrends
Training Signal Webtrends
Stefano Iaboni
 
Dot netcampus2015 green-template
Dot netcampus2015 green-templateDot netcampus2015 green-template
Dot netcampus2015 green-templateDotNetCampus
 
AntiPatterns: i vizi del programmatore
AntiPatterns: i vizi del programmatoreAntiPatterns: i vizi del programmatore
AntiPatterns: i vizi del programmatore
Manuel Scapolan
 
Managed Extensibility Framework (MEF)
Managed Extensibility Framework (MEF)Managed Extensibility Framework (MEF)
Managed Extensibility Framework (MEF)
Manuel Scapolan
 
Slide typescript - net campus
Slide typescript - net campusSlide typescript - net campus
Slide typescript - net campusDotNetCampus
 
ASP.NET Core - dove siamo arrivati
ASP.NET Core - dove siamo arrivatiASP.NET Core - dove siamo arrivati
ASP.NET Core - dove siamo arrivati
Andrea Dottor
 
Christmas greetings cards with blazor
Christmas greetings cards with blazorChristmas greetings cards with blazor
Christmas greetings cards with blazor
Nicolò Carandini
 
ASP.NET MVC 6 - uno sguardo al futuro
ASP.NET MVC 6 - uno sguardo al futuroASP.NET MVC 6 - uno sguardo al futuro
ASP.NET MVC 6 - uno sguardo al futuro
Andrea Dottor
 
Wasm and Blazor CDays keynote
Wasm and Blazor CDays keynoteWasm and Blazor CDays keynote
Wasm and Blazor CDays keynote
Nicolò Carandini
 
Javascript task automation
Javascript task automationJavascript task automation
Javascript task automationDotNetCampus
 
Architetttura Della Soluzione
Architetttura Della SoluzioneArchitetttura Della Soluzione
Architetttura Della SoluzioneLuca Milan
 
Dependency injection questa sconosciuta
Dependency injection questa sconosciutaDependency injection questa sconosciuta
Dependency injection questa sconosciuta
Andrea Dottor
 
ARCHITETTURA DI UN'APPLICAZIONE SCALABILE
ARCHITETTURA DI UN'APPLICAZIONE SCALABILEARCHITETTURA DI UN'APPLICAZIONE SCALABILE
ARCHITETTURA DI UN'APPLICAZIONE SCALABILE
DotNetCampus
 
Intelligenza artificiale nel mondo front-end - CodeGen2021
Intelligenza artificiale nel mondo front-end - CodeGen2021Intelligenza artificiale nel mondo front-end - CodeGen2021
Intelligenza artificiale nel mondo front-end - CodeGen2021
Michele Aponte
 
APPSTUDIO: DA ZERO ALLO STORE IN 50 MINUTI!
APPSTUDIO: DA ZERO ALLO STORE IN 50 MINUTI!APPSTUDIO: DA ZERO ALLO STORE IN 50 MINUTI!
APPSTUDIO: DA ZERO ALLO STORE IN 50 MINUTI!
DotNetCampus
 

What's hot (20)

Actions on Google e Alexa skills per .NET lovers
Actions on Google e Alexa skills per .NET loversActions on Google e Alexa skills per .NET lovers
Actions on Google e Alexa skills per .NET lovers
 
DotNetCampus - Continuous Integration con Sql Server
DotNetCampus - Continuous Integration con Sql ServerDotNetCampus - Continuous Integration con Sql Server
DotNetCampus - Continuous Integration con Sql Server
 
Del furia signalr-to-the-max
Del furia   signalr-to-the-maxDel furia   signalr-to-the-max
Del furia signalr-to-the-max
 
Javascript task automation
Javascript task automationJavascript task automation
Javascript task automation
 
Introduzione a Service Fabric e Actor Model
Introduzione a Service Fabric e Actor ModelIntroduzione a Service Fabric e Actor Model
Introduzione a Service Fabric e Actor Model
 
Training Signal Webtrends
Training Signal WebtrendsTraining Signal Webtrends
Training Signal Webtrends
 
Dot netcampus2015 green-template
Dot netcampus2015 green-templateDot netcampus2015 green-template
Dot netcampus2015 green-template
 
AntiPatterns: i vizi del programmatore
AntiPatterns: i vizi del programmatoreAntiPatterns: i vizi del programmatore
AntiPatterns: i vizi del programmatore
 
Managed Extensibility Framework (MEF)
Managed Extensibility Framework (MEF)Managed Extensibility Framework (MEF)
Managed Extensibility Framework (MEF)
 
Slide typescript - net campus
Slide typescript - net campusSlide typescript - net campus
Slide typescript - net campus
 
ASP.NET Core - dove siamo arrivati
ASP.NET Core - dove siamo arrivatiASP.NET Core - dove siamo arrivati
ASP.NET Core - dove siamo arrivati
 
Christmas greetings cards with blazor
Christmas greetings cards with blazorChristmas greetings cards with blazor
Christmas greetings cards with blazor
 
ASP.NET MVC 6 - uno sguardo al futuro
ASP.NET MVC 6 - uno sguardo al futuroASP.NET MVC 6 - uno sguardo al futuro
ASP.NET MVC 6 - uno sguardo al futuro
 
Wasm and Blazor CDays keynote
Wasm and Blazor CDays keynoteWasm and Blazor CDays keynote
Wasm and Blazor CDays keynote
 
Javascript task automation
Javascript task automationJavascript task automation
Javascript task automation
 
Architetttura Della Soluzione
Architetttura Della SoluzioneArchitetttura Della Soluzione
Architetttura Della Soluzione
 
Dependency injection questa sconosciuta
Dependency injection questa sconosciutaDependency injection questa sconosciuta
Dependency injection questa sconosciuta
 
ARCHITETTURA DI UN'APPLICAZIONE SCALABILE
ARCHITETTURA DI UN'APPLICAZIONE SCALABILEARCHITETTURA DI UN'APPLICAZIONE SCALABILE
ARCHITETTURA DI UN'APPLICAZIONE SCALABILE
 
Intelligenza artificiale nel mondo front-end - CodeGen2021
Intelligenza artificiale nel mondo front-end - CodeGen2021Intelligenza artificiale nel mondo front-end - CodeGen2021
Intelligenza artificiale nel mondo front-end - CodeGen2021
 
APPSTUDIO: DA ZERO ALLO STORE IN 50 MINUTI!
APPSTUDIO: DA ZERO ALLO STORE IN 50 MINUTI!APPSTUDIO: DA ZERO ALLO STORE IN 50 MINUTI!
APPSTUDIO: DA ZERO ALLO STORE IN 50 MINUTI!
 

Viewers also liked

Pronti per la legge sulla data protection GDPR? No Panic! - Domenico Maracci,...
Pronti per la legge sulla data protection GDPR? No Panic! - Domenico Maracci,...Pronti per la legge sulla data protection GDPR? No Panic! - Domenico Maracci,...
Pronti per la legge sulla data protection GDPR? No Panic! - Domenico Maracci,...
Codemotion
 
Cyber Wars in the Cyber Space - Andrea Pompili - Codemotion Rome 2017
Cyber Wars in the Cyber Space - Andrea Pompili - Codemotion Rome 2017Cyber Wars in the Cyber Space - Andrea Pompili - Codemotion Rome 2017
Cyber Wars in the Cyber Space - Andrea Pompili - Codemotion Rome 2017
Codemotion
 
Il game audio come processo ingegneristico - Davide Pensato - Codemotion Rome...
Il game audio come processo ingegneristico - Davide Pensato - Codemotion Rome...Il game audio come processo ingegneristico - Davide Pensato - Codemotion Rome...
Il game audio come processo ingegneristico - Davide Pensato - Codemotion Rome...
Codemotion
 
Comics and immersive storytelling in Virtual Reality - Fabio Corrirossi - Cod...
Comics and immersive storytelling in Virtual Reality - Fabio Corrirossi - Cod...Comics and immersive storytelling in Virtual Reality - Fabio Corrirossi - Cod...
Comics and immersive storytelling in Virtual Reality - Fabio Corrirossi - Cod...
Codemotion
 
Galateo semi-serio dell'Open Source - Luigi Dell' Aquila - Codemotion Rome 2017
Galateo semi-serio dell'Open Source -  Luigi Dell' Aquila - Codemotion Rome 2017Galateo semi-serio dell'Open Source -  Luigi Dell' Aquila - Codemotion Rome 2017
Galateo semi-serio dell'Open Source - Luigi Dell' Aquila - Codemotion Rome 2017
Codemotion
 
Docker Inside/Out: the ‘real’ real-world of stacking containers in production...
Docker Inside/Out: the ‘real’ real-world of stacking containers in production...Docker Inside/Out: the ‘real’ real-world of stacking containers in production...
Docker Inside/Out: the ‘real’ real-world of stacking containers in production...
Codemotion
 
Container orchestration: the cold war - Giulio De Donato - Codemotion Rome 2017
Container orchestration: the cold war - Giulio De Donato - Codemotion Rome 2017Container orchestration: the cold war - Giulio De Donato - Codemotion Rome 2017
Container orchestration: the cold war - Giulio De Donato - Codemotion Rome 2017
Codemotion
 
S3, Cassandra or Outer Space? Dumping Time Series Data using Spark - Demi Be...
S3, Cassandra or Outer Space? Dumping Time Series Data using Spark  - Demi Be...S3, Cassandra or Outer Space? Dumping Time Series Data using Spark  - Demi Be...
S3, Cassandra or Outer Space? Dumping Time Series Data using Spark - Demi Be...
Codemotion
 
Barbarians at the Gate(way) - Dave Lewis - Codemotion Rome 2017
Barbarians at the Gate(way) - Dave Lewis - Codemotion Rome 2017Barbarians at the Gate(way) - Dave Lewis - Codemotion Rome 2017
Barbarians at the Gate(way) - Dave Lewis - Codemotion Rome 2017
Codemotion
 
Cyber Security in Multi Cloud Architecture - Luca Di Bari - Codemotion Rome 2017
Cyber Security in Multi Cloud Architecture - Luca Di Bari - Codemotion Rome 2017Cyber Security in Multi Cloud Architecture - Luca Di Bari - Codemotion Rome 2017
Cyber Security in Multi Cloud Architecture - Luca Di Bari - Codemotion Rome 2017
Codemotion
 
Handle insane devices traffic using Google Cloud Platform - Andrea Ulisse - C...
Handle insane devices traffic using Google Cloud Platform - Andrea Ulisse - C...Handle insane devices traffic using Google Cloud Platform - Andrea Ulisse - C...
Handle insane devices traffic using Google Cloud Platform - Andrea Ulisse - C...
Codemotion
 
Commodore 64 Mon Amour(2): sprite multiplexing. Il caso Catalypse e altre sto...
Commodore 64 Mon Amour(2): sprite multiplexing. Il caso Catalypse e altre sto...Commodore 64 Mon Amour(2): sprite multiplexing. Il caso Catalypse e altre sto...
Commodore 64 Mon Amour(2): sprite multiplexing. Il caso Catalypse e altre sto...
Codemotion
 
An Introduction to Apache Ignite - Mandhir Gidda - Codemotion Rome 2017
An Introduction to Apache Ignite - Mandhir Gidda - Codemotion Rome 2017An Introduction to Apache Ignite - Mandhir Gidda - Codemotion Rome 2017
An Introduction to Apache Ignite - Mandhir Gidda - Codemotion Rome 2017
Codemotion
 
The busy developer guide to Docker - Maurice de Beijer - Codemotion Rome 2017
The busy developer guide to Docker - Maurice de Beijer - Codemotion Rome 2017The busy developer guide to Docker - Maurice de Beijer - Codemotion Rome 2017
The busy developer guide to Docker - Maurice de Beijer - Codemotion Rome 2017
Codemotion
 
Component-Based UI Architectures for the Web - Andrew Rota - Codemotion Rome...
Component-Based UI Architectures for the Web  - Andrew Rota - Codemotion Rome...Component-Based UI Architectures for the Web  - Andrew Rota - Codemotion Rome...
Component-Based UI Architectures for the Web - Andrew Rota - Codemotion Rome...
Codemotion
 
Kunos Simulazioni and Assetto Corsa, behind the scenes- Alessandro Piva, Fabr...
Kunos Simulazioni and Assetto Corsa, behind the scenes- Alessandro Piva, Fabr...Kunos Simulazioni and Assetto Corsa, behind the scenes- Alessandro Piva, Fabr...
Kunos Simulazioni and Assetto Corsa, behind the scenes- Alessandro Piva, Fabr...
Codemotion
 
Meetup Code Garden Roma e Java User Group Roma: metodi asincroni con Spring -...
Meetup Code Garden Roma e Java User Group Roma: metodi asincroni con Spring -...Meetup Code Garden Roma e Java User Group Roma: metodi asincroni con Spring -...
Meetup Code Garden Roma e Java User Group Roma: metodi asincroni con Spring -...
Codemotion
 
Monitoring Big Data Systems Done "The Simple Way" - Demi Ben-Ari - Codemotion...
Monitoring Big Data Systems Done "The Simple Way" - Demi Ben-Ari - Codemotion...Monitoring Big Data Systems Done "The Simple Way" - Demi Ben-Ari - Codemotion...
Monitoring Big Data Systems Done "The Simple Way" - Demi Ben-Ari - Codemotion...
Codemotion
 
Event-Sourcing your React-Redux applications - Maurice de Beijer - Codemotion...
Event-Sourcing your React-Redux applications - Maurice de Beijer - Codemotion...Event-Sourcing your React-Redux applications - Maurice de Beijer - Codemotion...
Event-Sourcing your React-Redux applications - Maurice de Beijer - Codemotion...
Codemotion
 
Microservice Plumbing - Glynn Bird - Codemotion Rome 2017
Microservice Plumbing  - Glynn Bird - Codemotion Rome 2017Microservice Plumbing  - Glynn Bird - Codemotion Rome 2017
Microservice Plumbing - Glynn Bird - Codemotion Rome 2017
Codemotion
 

Viewers also liked (20)

Pronti per la legge sulla data protection GDPR? No Panic! - Domenico Maracci,...
Pronti per la legge sulla data protection GDPR? No Panic! - Domenico Maracci,...Pronti per la legge sulla data protection GDPR? No Panic! - Domenico Maracci,...
Pronti per la legge sulla data protection GDPR? No Panic! - Domenico Maracci,...
 
Cyber Wars in the Cyber Space - Andrea Pompili - Codemotion Rome 2017
Cyber Wars in the Cyber Space - Andrea Pompili - Codemotion Rome 2017Cyber Wars in the Cyber Space - Andrea Pompili - Codemotion Rome 2017
Cyber Wars in the Cyber Space - Andrea Pompili - Codemotion Rome 2017
 
Il game audio come processo ingegneristico - Davide Pensato - Codemotion Rome...
Il game audio come processo ingegneristico - Davide Pensato - Codemotion Rome...Il game audio come processo ingegneristico - Davide Pensato - Codemotion Rome...
Il game audio come processo ingegneristico - Davide Pensato - Codemotion Rome...
 
Comics and immersive storytelling in Virtual Reality - Fabio Corrirossi - Cod...
Comics and immersive storytelling in Virtual Reality - Fabio Corrirossi - Cod...Comics and immersive storytelling in Virtual Reality - Fabio Corrirossi - Cod...
Comics and immersive storytelling in Virtual Reality - Fabio Corrirossi - Cod...
 
Galateo semi-serio dell'Open Source - Luigi Dell' Aquila - Codemotion Rome 2017
Galateo semi-serio dell'Open Source -  Luigi Dell' Aquila - Codemotion Rome 2017Galateo semi-serio dell'Open Source -  Luigi Dell' Aquila - Codemotion Rome 2017
Galateo semi-serio dell'Open Source - Luigi Dell' Aquila - Codemotion Rome 2017
 
Docker Inside/Out: the ‘real’ real-world of stacking containers in production...
Docker Inside/Out: the ‘real’ real-world of stacking containers in production...Docker Inside/Out: the ‘real’ real-world of stacking containers in production...
Docker Inside/Out: the ‘real’ real-world of stacking containers in production...
 
Container orchestration: the cold war - Giulio De Donato - Codemotion Rome 2017
Container orchestration: the cold war - Giulio De Donato - Codemotion Rome 2017Container orchestration: the cold war - Giulio De Donato - Codemotion Rome 2017
Container orchestration: the cold war - Giulio De Donato - Codemotion Rome 2017
 
S3, Cassandra or Outer Space? Dumping Time Series Data using Spark - Demi Be...
S3, Cassandra or Outer Space? Dumping Time Series Data using Spark  - Demi Be...S3, Cassandra or Outer Space? Dumping Time Series Data using Spark  - Demi Be...
S3, Cassandra or Outer Space? Dumping Time Series Data using Spark - Demi Be...
 
Barbarians at the Gate(way) - Dave Lewis - Codemotion Rome 2017
Barbarians at the Gate(way) - Dave Lewis - Codemotion Rome 2017Barbarians at the Gate(way) - Dave Lewis - Codemotion Rome 2017
Barbarians at the Gate(way) - Dave Lewis - Codemotion Rome 2017
 
Cyber Security in Multi Cloud Architecture - Luca Di Bari - Codemotion Rome 2017
Cyber Security in Multi Cloud Architecture - Luca Di Bari - Codemotion Rome 2017Cyber Security in Multi Cloud Architecture - Luca Di Bari - Codemotion Rome 2017
Cyber Security in Multi Cloud Architecture - Luca Di Bari - Codemotion Rome 2017
 
Handle insane devices traffic using Google Cloud Platform - Andrea Ulisse - C...
Handle insane devices traffic using Google Cloud Platform - Andrea Ulisse - C...Handle insane devices traffic using Google Cloud Platform - Andrea Ulisse - C...
Handle insane devices traffic using Google Cloud Platform - Andrea Ulisse - C...
 
Commodore 64 Mon Amour(2): sprite multiplexing. Il caso Catalypse e altre sto...
Commodore 64 Mon Amour(2): sprite multiplexing. Il caso Catalypse e altre sto...Commodore 64 Mon Amour(2): sprite multiplexing. Il caso Catalypse e altre sto...
Commodore 64 Mon Amour(2): sprite multiplexing. Il caso Catalypse e altre sto...
 
An Introduction to Apache Ignite - Mandhir Gidda - Codemotion Rome 2017
An Introduction to Apache Ignite - Mandhir Gidda - Codemotion Rome 2017An Introduction to Apache Ignite - Mandhir Gidda - Codemotion Rome 2017
An Introduction to Apache Ignite - Mandhir Gidda - Codemotion Rome 2017
 
The busy developer guide to Docker - Maurice de Beijer - Codemotion Rome 2017
The busy developer guide to Docker - Maurice de Beijer - Codemotion Rome 2017The busy developer guide to Docker - Maurice de Beijer - Codemotion Rome 2017
The busy developer guide to Docker - Maurice de Beijer - Codemotion Rome 2017
 
Component-Based UI Architectures for the Web - Andrew Rota - Codemotion Rome...
Component-Based UI Architectures for the Web  - Andrew Rota - Codemotion Rome...Component-Based UI Architectures for the Web  - Andrew Rota - Codemotion Rome...
Component-Based UI Architectures for the Web - Andrew Rota - Codemotion Rome...
 
Kunos Simulazioni and Assetto Corsa, behind the scenes- Alessandro Piva, Fabr...
Kunos Simulazioni and Assetto Corsa, behind the scenes- Alessandro Piva, Fabr...Kunos Simulazioni and Assetto Corsa, behind the scenes- Alessandro Piva, Fabr...
Kunos Simulazioni and Assetto Corsa, behind the scenes- Alessandro Piva, Fabr...
 
Meetup Code Garden Roma e Java User Group Roma: metodi asincroni con Spring -...
Meetup Code Garden Roma e Java User Group Roma: metodi asincroni con Spring -...Meetup Code Garden Roma e Java User Group Roma: metodi asincroni con Spring -...
Meetup Code Garden Roma e Java User Group Roma: metodi asincroni con Spring -...
 
Monitoring Big Data Systems Done "The Simple Way" - Demi Ben-Ari - Codemotion...
Monitoring Big Data Systems Done "The Simple Way" - Demi Ben-Ari - Codemotion...Monitoring Big Data Systems Done "The Simple Way" - Demi Ben-Ari - Codemotion...
Monitoring Big Data Systems Done "The Simple Way" - Demi Ben-Ari - Codemotion...
 
Event-Sourcing your React-Redux applications - Maurice de Beijer - Codemotion...
Event-Sourcing your React-Redux applications - Maurice de Beijer - Codemotion...Event-Sourcing your React-Redux applications - Maurice de Beijer - Codemotion...
Event-Sourcing your React-Redux applications - Maurice de Beijer - Codemotion...
 
Microservice Plumbing - Glynn Bird - Codemotion Rome 2017
Microservice Plumbing  - Glynn Bird - Codemotion Rome 2017Microservice Plumbing  - Glynn Bird - Codemotion Rome 2017
Microservice Plumbing - Glynn Bird - Codemotion Rome 2017
 

Similar to Xamarin.Forms Performance Tips & Tricks - Francesco Bonacci - Codemotion Rome 2017

Mobile UI Design
Mobile UI DesignMobile UI Design
Mobile UI Design
Simone Viani
 
April 2010 - Seam unifies JEE5
April 2010 - Seam unifies JEE5April 2010 - Seam unifies JEE5
April 2010 - Seam unifies JEE5JBug Italy
 
Seam unifies Java EE by Massimiliano Ciccazzo
Seam unifies Java EE by Massimiliano CiccazzoSeam unifies Java EE by Massimiliano Ciccazzo
Seam unifies Java EE by Massimiliano Ciccazzo
Java User Group Roma
 
Migliora il tuo codice con knockout.js
Migliora il tuo codice con knockout.jsMigliora il tuo codice con knockout.js
Migliora il tuo codice con knockout.js
Andrea Dottor
 
Introduzione ad angular 7/8
Introduzione ad angular 7/8Introduzione ad angular 7/8
Introduzione ad angular 7/8
Valerio Radice
 
Corso WebApp iOS - Lezione 06: Web Development for iOS Devices
Corso WebApp iOS - Lezione 06:   Web Development for iOS DevicesCorso WebApp iOS - Lezione 06:   Web Development for iOS Devices
Corso WebApp iOS - Lezione 06: Web Development for iOS Devices
Andrea Picchi
 
DNM19 Sessione2 Orchard Temi e Layout (Ita)
DNM19 Sessione2 Orchard Temi e Layout (Ita)DNM19 Sessione2 Orchard Temi e Layout (Ita)
DNM19 Sessione2 Orchard Temi e Layout (Ita)
Alessandro Giorgetti
 
Novità di Asp.Net 4.0
Novità di Asp.Net 4.0Novità di Asp.Net 4.0
Novità di Asp.Net 4.0
Gian Maria Ricci
 
DNM19 Sessione1 Orchard Primo Impatto (ita)
DNM19 Sessione1 Orchard Primo Impatto (ita)DNM19 Sessione1 Orchard Primo Impatto (ita)
DNM19 Sessione1 Orchard Primo Impatto (ita)
Alessandro Giorgetti
 
Deep diving C# 4 (Raffaele Rialdi)
Deep diving C# 4 (Raffaele Rialdi)Deep diving C# 4 (Raffaele Rialdi)
Deep diving C# 4 (Raffaele Rialdi)DotNetMarche
 
Asp.net 4 Community Tour VS2010
Asp.net 4 Community Tour VS2010Asp.net 4 Community Tour VS2010
Asp.net 4 Community Tour VS2010
Fabrizio Bernabei
 
GWT vs CSS3
GWT vs CSS3GWT vs CSS3
GWT vs CSS3
GWTcon
 
Uno sguardo a CQRS ed EventSourcing
Uno sguardo a CQRS ed EventSourcingUno sguardo a CQRS ed EventSourcing
Uno sguardo a CQRS ed EventSourcingAlessandro Melchiori
 
Blazor: are we ready for the launch?
Blazor: are we ready for the launch?Blazor: are we ready for the launch?
Blazor: are we ready for the launch?
Andrea Agnoletto
 
react-it.pdf
react-it.pdfreact-it.pdf
react-it.pdf
ssuser65180a
 
Enterprise Spring and Flex applications
Enterprise Spring and Flex applicationsEnterprise Spring and Flex applications
Enterprise Spring and Flex applications
marcocasario
 
Laboratorio internet 9: Sviluppo delle funzioni
Laboratorio internet 9: Sviluppo delle funzioniLaboratorio internet 9: Sviluppo delle funzioni
Laboratorio internet 9: Sviluppo delle funzioni
Roberto Polillo
 
Joomla! 1.5: CMS a mani tese verso gli sviluppatori
Joomla! 1.5: CMS a mani tese verso gli sviluppatoriJoomla! 1.5: CMS a mani tese verso gli sviluppatori
Joomla! 1.5: CMS a mani tese verso gli sviluppatori
GrUSP
 
Joomla! 1.5: CMS a mani tese verso gli sviluppatori
Joomla! 1.5: CMS a mani tese verso gli sviluppatoriJoomla! 1.5: CMS a mani tese verso gli sviluppatori
Joomla! 1.5: CMS a mani tese verso gli sviluppatori
Alessandro Nadalin
 

Similar to Xamarin.Forms Performance Tips & Tricks - Francesco Bonacci - Codemotion Rome 2017 (20)

Mobile UI Design
Mobile UI DesignMobile UI Design
Mobile UI Design
 
April 2010 - Seam unifies JEE5
April 2010 - Seam unifies JEE5April 2010 - Seam unifies JEE5
April 2010 - Seam unifies JEE5
 
Seam unifies Java EE by Massimiliano Ciccazzo
Seam unifies Java EE by Massimiliano CiccazzoSeam unifies Java EE by Massimiliano Ciccazzo
Seam unifies Java EE by Massimiliano Ciccazzo
 
Migliora il tuo codice con knockout.js
Migliora il tuo codice con knockout.jsMigliora il tuo codice con knockout.js
Migliora il tuo codice con knockout.js
 
Introduzione ad angular 7/8
Introduzione ad angular 7/8Introduzione ad angular 7/8
Introduzione ad angular 7/8
 
HTML5
HTML5HTML5
HTML5
 
Corso WebApp iOS - Lezione 06: Web Development for iOS Devices
Corso WebApp iOS - Lezione 06:   Web Development for iOS DevicesCorso WebApp iOS - Lezione 06:   Web Development for iOS Devices
Corso WebApp iOS - Lezione 06: Web Development for iOS Devices
 
DNM19 Sessione2 Orchard Temi e Layout (Ita)
DNM19 Sessione2 Orchard Temi e Layout (Ita)DNM19 Sessione2 Orchard Temi e Layout (Ita)
DNM19 Sessione2 Orchard Temi e Layout (Ita)
 
Novità di Asp.Net 4.0
Novità di Asp.Net 4.0Novità di Asp.Net 4.0
Novità di Asp.Net 4.0
 
DNM19 Sessione1 Orchard Primo Impatto (ita)
DNM19 Sessione1 Orchard Primo Impatto (ita)DNM19 Sessione1 Orchard Primo Impatto (ita)
DNM19 Sessione1 Orchard Primo Impatto (ita)
 
Deep diving C# 4 (Raffaele Rialdi)
Deep diving C# 4 (Raffaele Rialdi)Deep diving C# 4 (Raffaele Rialdi)
Deep diving C# 4 (Raffaele Rialdi)
 
Asp.net 4 Community Tour VS2010
Asp.net 4 Community Tour VS2010Asp.net 4 Community Tour VS2010
Asp.net 4 Community Tour VS2010
 
GWT vs CSS3
GWT vs CSS3GWT vs CSS3
GWT vs CSS3
 
Uno sguardo a CQRS ed EventSourcing
Uno sguardo a CQRS ed EventSourcingUno sguardo a CQRS ed EventSourcing
Uno sguardo a CQRS ed EventSourcing
 
Blazor: are we ready for the launch?
Blazor: are we ready for the launch?Blazor: are we ready for the launch?
Blazor: are we ready for the launch?
 
react-it.pdf
react-it.pdfreact-it.pdf
react-it.pdf
 
Enterprise Spring and Flex applications
Enterprise Spring and Flex applicationsEnterprise Spring and Flex applications
Enterprise Spring and Flex applications
 
Laboratorio internet 9: Sviluppo delle funzioni
Laboratorio internet 9: Sviluppo delle funzioniLaboratorio internet 9: Sviluppo delle funzioni
Laboratorio internet 9: Sviluppo delle funzioni
 
Joomla! 1.5: CMS a mani tese verso gli sviluppatori
Joomla! 1.5: CMS a mani tese verso gli sviluppatoriJoomla! 1.5: CMS a mani tese verso gli sviluppatori
Joomla! 1.5: CMS a mani tese verso gli sviluppatori
 
Joomla! 1.5: CMS a mani tese verso gli sviluppatori
Joomla! 1.5: CMS a mani tese verso gli sviluppatoriJoomla! 1.5: CMS a mani tese verso gli sviluppatori
Joomla! 1.5: CMS a mani tese verso gli sviluppatori
 

More from Codemotion

Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Codemotion
 
Pompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyPompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending story
Codemotion
 
Pastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaPastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storia
Codemotion
 
Pennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserPennisi - Essere Richard Altwasser
Pennisi - Essere Richard Altwasser
Codemotion
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Codemotion
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Codemotion
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Codemotion
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Codemotion
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Codemotion
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Codemotion
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Codemotion
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Codemotion
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Codemotion
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Codemotion
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Codemotion
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
Codemotion
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Codemotion
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Codemotion
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Codemotion
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Codemotion
 

More from Codemotion (20)

Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
 
Pompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyPompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending story
 
Pastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaPastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storia
 
Pennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserPennisi - Essere Richard Altwasser
Pennisi - Essere Richard Altwasser
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
 

Xamarin.Forms Performance Tips & Tricks - Francesco Bonacci - Codemotion Rome 2017

  • 1. Xamarin.Forms Performance Tips & Tricks Francesco Bonacci ROME 24-25 MARCH 2017
  • 2.
  • 3. @xamarinhq lo adora, lo sviluppatore lo teme e il cliente lo odia... Forse un pò mal giudicato.. È davvero sempre colpa del framework? Il dilemma degli ultimi tempi assieme a PCL vs. SP O odia voi? Vediamo come risolvere!
  • 4. 1. Native vs. Forms 2. XamlC 3. View 4. Layout 5. Binding 6. UI Thread 7. Forms Embedding
  • 5.
  • 6. iOS C# UI Windows C# UIAndroid C# UI Shared C# Mobile  C# Wrapper per l’accesso ad API native  Riutilizzo codebase comune  Performance ~ Approccio Silo  Progetto della UI dipendente da tool e modalità native
  • 7. Shared C# Mobile Xamarin.Forms  Xaml/C# UI codebase  API di Sistema astratte  Data Binding e MVVM  Performance < Xamarin.Native
  • 8.  Xamarin.Forms non è adatto a tutti i tipi di app  OK per applicazioni di utilità o data-entry x Non ideale se l’obiettivo finale è produrre effetti grafici sfavillanti  Primo approccio affrontato per chi viene dal mondo WPF, WinRT, UWP ecc.  Occorrerebbe prima conoscere quello che c’è sotto...  Spesso usato da team per la prima fase di prototipaggio dell’applicazione  Poi se il cliente non è contento si passa a Native… MA se ci facciamo bastare quello che offre Xamarin.Forms?
  • 9. Xamarin.Forms non è da sottovalutare:  Si possono creare UI accattivanti e anche complesse github.com/xamarinhq/app-evolve
  • 10. Xamarin.Forms non è da sottovalutare:  Si possono creare UI accattivanti e anche complesse  Si evita di replicare il codice della UI github.com/xamarinhq/app-evolve iOS Android UWP *Statistiche prese dall’app Xamarin Evolve 2016 Codice cross-platform
  • 11. Xamarin.Forms non è da sopravvalutare:  Occorre tener conto dell’ulteriore Layer di astrazione  E’ un framework ancora giovane  Lo XAML non è lo stesso di UWP…  Non si può pensare di sviluppare una pagina Forms senza sapere quello che c’è sotto!  A volte l’unica cosa da fare è utilizzare bit nativi - aka Custom Renderer ed Effect
  • 12. Nel progettare la UI con Xamarin.Forms bisogna:  Utilizzare i controlli più adatti per lo scenario in mente  Non eccedere con la densità dell’albero visuale (Visual Tree)  Sfruttare a proprio vantaggio le funzionalità (nascoste) di Xamarin  L’HW dell’utente medio è pessimo  Prendere come riferimento la fascia medio-bassa  Avere buon senso… … E seguire le prossime linee guida
  • 13.
  • 14. XamlCompilationOptions Compile Skip Compilazione AOT (in CIL) Compilazione JIT Se si utilizza XAML per la UI si può specificare la modalità di compilazione:  Velocizza il caricamento degli elementi visuali  Riduce la dimensione del pacchetto finale  Tempi di compilazione più lunghi  Valore di default per garantire retro compatibilità  Nessuna validazione dello XAML compile-time
  • 15. A livello di Assembly  E’ buona prassi farlo nel file AssemblyInfo.cs A livello di Pagina
  • 16. bit.ly/2nQ5JZw 0 100 200 300 400 500 600 700 800 Android Initialization Time (Avg) Skip Compile  Time profiled on Page InitializeComponent()  Average calculated on a population of size 20  HW: LG Nexus 5X with Android 7.1 Nougat ms
  • 17. bit.ly/2nQ5JZw 0 100 200 300 400 500 600 700 800 UWP Initialization Time (Avg) Skip Compile ms  Time profiled on Page InitializeComponent()  Average calculated on a population of size 20  HW: Lumia 640 LTE with Build 10.0.14393.0
  • 18. bit.ly/2nQ5JZw 0 20 40 60 80 100 120 iOS Initialization Time (Avg) Skip Compile  Time profiled on Page InitializeComponent()  Average calculated on a population of size 20  HW: iPhone Simulator 7 Plus with iOS 10.2 ms
  • 19.
  • 20. Una View in Forms rappresenta un nodo nell’albero della pagina (Visual Tree) avente proprietà visuali ed un comportamento
  • 21. Una View in Forms rappresenta un nodo nell’albero della pagina (Visual Tree) avente proprietà visuali ed un comportamento Rappresenta l’elemento di più basso livello, assieme a Page, nella gerarchia di ereditarietà di Xamarin.Forms Esempi: Label, Editor, Button, Image…
  • 22. La creazione di una View in Xamarin.Forms è suddivisa in due fasi: Inflating Istanziamento della View Rendering Aggiunta all’albero visuale (Automatica in Xaml)public MainPage() { var stackLayout = new StackLayout(); stackLayout.Children.Add(new Label() { Text = "Hello Codemotion!" }); //... } public MainPage() { //... Content = stackLayout; }
  • 23.  Evitare di usare trasparenza e opacità, specialmente in Android  Preferire le Bindable Property TranslationX e TranslationY, piuttosto che Padding e Margin, per eseguire riordinamenti post-layout  Non specificare i valori di default delle proprietà visuali, specialmente VerticalOptions e HorizontalOptions  Vengono scatenati cicli di misura superflui
  • 24. Per far seguire porzioni di testo con caratteristiche diverse preferire la Bindable Property FormattedText di Label <StackLayout Orientation="Horizontal"> <Label Text="Hello" TextColor="Blue"/> <Label Text="Codemotion!" TextColor="Orange"/> </StackLayout> <Label> <Label.FormattedText> <FormattedString> <Span Text="Hello " ForegroundColor="Blue"/> <Span Text="Codemotion!" ForegroundColor="Orange" /> </FormattedString> </Label.FormattedText> </Label>
  • 25. Le Bindable Property VerticalTextAlignment e HorizontalTextAlignment di tipo TextAlignment sono ottimizzate per posizionare elementi visuali di tipo Label <Label Text="Hello Codemotion!" VerticalOptions="Center" HorizontalOptions="Center"/> <Label Text="Hello Codemotion!" VerticalTextAlignment="Center" HorizontalTextAlignment="Center"/>
  • 26. <Image Source="resource.png"/> <Image> <Image.Source> <FileImageSource File="file.png"/> </Image.Source> </Image> Image.Source = ImageSource. FromResource("resource.png"); Image.Source = ImageSource. FromFile("file.png"); Preferire come ImageSource un immagine salvata nel File System piuttosto che un File di Risorse
  • 27.  Disabilitare Opacità   Problematiche in Android  e.g. JPG CMYK non supportati  Da preferire downscaling e manipolazione server-side <Image IsOpaque="False"/> Eventualmente non reinventare la ruota… <ffimageloading:CachedImage LoadingPlaceholder="loading.png" DownsampleToViewSize="True"> <ffimageloading:CachedImage.Transformations> <ffimageloading:GrayscaleTransformation /> </ffimageloading:CachedImage.Transformations> </ffimageloading:CachedImage> github.com/luberda-molinet/FFImageLoading
  • 28. Problematiche fino all’introduzione di una strategia di caching delle celle in Xamarin.Forms 2.0 public class CustomListView : ListView { public CustomListView(ListViewCachingStrategy cachingStrategy) : base(cachingStrategy) { //... } } <ListView CachingStrategy="RecycleElement"/> var listView = new ListView( ListViewCachingStrategy.RecycleElement); Se controllo custom, esporre il costruttore della classe base
  • 29. ListViewCachingStrategy RecycleElement RetainElement  La ListView mantiene un pool di celle di dimensione pari alla finestra visuale di scorrimento (Cell Recycling)  Ideale se il layout delle celle è statico  Ad esempio se non si utilizzano DataTemplateSelector  Valore di default per garantire retrocompatibilità  La ListView genera una nuova cella per ogni elemento della lista (Cell Retention)  Ideale se si utilizza un alto numero di Binding
  • 30.  Preferire IList<T> anziché IEnumerable<T> come sorgente ItemsSource della ListView  Supporto ad accesso casuale  Se si utilizza RecycleElement come strategia di Caching, rimuovere i Binding della cella ed aggiornarli nell’handler OnBindingContextChanged protected override void OnBindingContextChanged() { base.OnBindingContextChanged(); var item = BindingContext as ItemViewModel; if (item != null) { item.Title = TitleLabel.Text; } }
  • 31. <ScrollView> <StackLayout> <Label Text="Header" /> <ListView /> <Label Text="Footer" /> </StackLayout> </ScrollView> Per abilitare lo scrolling all’interno di pagine contenenti ListView utilizzare i DataTemplate <ListView Header="Header" Footer="Footer"> <ListView.HeaderTemplate> <DataTemplate> <Label Text="{Binding .}" /> </DataTemplate> </ListView.HeaderTemplate> <ListView.FooterTemplate> <DataTemplate> <Label Text="{Binding .}" /> </DataTemplate> </ListView.FooterTemplate> </ListView> HeaderTemplate e FooterTemplate
  • 32.
  • 33. Un Layout in Forms rappresenta un nodo nell’albero della pagina avente proprietà visuali e un comportamento È responsabile della posizione e dimensione dei suoi nodi figlio
  • 34. Eredita da VisualElement, Element ma non da View Esempi: Grid, StackLayout, AbsoluteLayout... Un Layout in Forms rappresenta un nodo nell’albero della pagina avente proprietà visuali e un comportamento È responsabile della posizione e dimensione dei suoi nodi figlio
  • 35. La creazione e l’aggiornamento di un Layout in Xamarin.Forms attraversano due fasi (o cicli): Invalidation Cycle (IC)  Dal nodo di più basso livello, si notifica ricorsivamente il nodo padre dell’invalidazione (aggiornamento) del proprio Layout  Ha termine una volta raggiunto il nodo radice (e.g. Page) o se il padre decide di ignorare l’invalidazione Layout Cycle (LC)  A seguito dell’invalidazione e procedendo top-bottom, la pagina riorganizza il layout degli elementi etichettati come "invalidati"  La riorganizzazione termina con l’ultimo elemento invalidato
  • 36. No Si
  • 37. public enum InvalidationTrigger { Undefined = 0, MeasureChanged = 1 << 0, HorizontalOptionsChanged = 1 << 1, VerticalOptionsChanged = 1 << 2, SizeRequestChanged = 1 << 3, RendererReady = 1 << 4, MarginChanged = 1 << 5 } L’invalidazione di un Layout può essere causata da diversi fattori  Indicati dall’enumerativo InvalidationTrigger Ogni Layout può decidere di gestire a suo modo l’invalidazione di un figlio, eventualmente interrompendo il ciclo di invalidazione Lo sviluppatore può sfruttare l’interruzione di Layout di sistema (anche implementando il proprio) per guadagnare ms sull’IC
  • 38. Si No foreach child in layout.Children
  • 39.  Il Layout Cycle termina con il Layout() dell’ultimo elemento invalidato  L’implementazione dei metodi Measure e Layout è demandata ai Custom Renderer specifici per il Layout  Diversamente dall’Invalidation Cycle, non è possibile controllare il ciclo di Layout
  • 40.  Se si definisce una View da codice, è bene aggiungere la View contenitore all’albero visuale solo quando si è finito di manipolare la struttura delle sue subview  Altrimenti ulteriori cicli di Misure  Aggiungere View al VT nel costruttore e non in OnAppering()  Altrimenti ulteriori cicli di Invalidazione  Non utilizzare ForceLayout()  Non sostituire ListView con ScrollView+StackLayout  Nessuna virtualizzazione delle subview
  • 41. Grid organizza il layout dei suoi figli in celle individuate da Righe e Colonne  Permette di creare Layout composti senza eccessivo nesting  Occorre prestare attenzione all’utilizzo di Righe e Colonne per il dimensionamento
  • 42. L’invalidazione di una delle View figlie provoca l’invalidazione a catena del Visual Tree fino a Grid <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Label Text="Hello Codemotion!"/> <Label Grid.Row="1" Text="Hello Codemotion!"/> </Grid> E se l’elemento invalidato è un nodo foglia e nessun Layout interrompe il ciclo?! Grid organizza il layout dei suoi figli in celle individuate da Righe e Colonne
  • 43. Poiché lo spazio messo a disposizione degli elementi figlio è proporzionale alla superview ma indipendente dalle subview, Grid ignora eventuali notifiche di invalidazione dai suoi figli <Grid> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Label Text="Hello Codemotion!"/> <Label Grid.Row="1" Text="Hello Codemotion!"/> </Grid> Grid organizza il layout dei suoi figli in celle individuate da Righe e Colonne
  • 44. Poiché lo spazio messo a disposizione degli elementi figlio è fissato staticamente, Grid ignora eventuali notifiche di invalidazione dai suoi figli <Grid> <Grid.RowDefinitions> <RowDefinition Height="50"/> <RowDefinition Height="50"/> </Grid.RowDefinitions> <Label Text="Hello Codemotion!"/> <Label Grid.Row="1" Text="Hello Codemotion!"/> </Grid> Grid organizza il layout dei suoi figli in celle individuate da Righe e Colonne
  • 45. Utilizzare le Bindable Property RowSpacing e ColumnSpacing per controllare la distanza tra Righe e Colonne <Grid> <Grid.RowDefinitions> <RowDefinition Height="50"/> <RowDefinition Height="10"/> <RowDefinition Height="50"/> </Grid.RowDefinitions> <Label Text="Hello Codemotion!"/> <Label Grid.Row="1" Text="Hello Codemotion!"/> </Grid> <Grid RowSpacing="10"> <Grid.RowDefinitions> <RowDefinition Height="50"/> <RowDefinition Height="50"/> </Grid.RowDefinitions> <Label Text="Hello Codemotion!"/> <Label Grid.Row="1" Text="Hello Codemotion!"/> </Grid>
  • 46. StackLayout organizza il layout dei suoi figli su di un’unica riga o colonna  Ideale per creare Layout semplici impilando sequenzialmente controlli  Può portare ad un eccessivo nesting del VT
  • 47. L’invalidazione di una delle View figlie provoca l’invalidazione a catena del Visual Tree fino a StackLayout E se l’elemento invalidato è un nodo foglia e nessun Layout interrompe il ciclo?! <StackLayout> <Label Text="Hello Codemotion!"/> <Label Text="Hello Codemotion!"/> </StackLayout> StackLayout organizza il layout dei suoi figli su di un’unica riga o colonna Grid - Auto Sizing
  • 48. Golden Rule “ Don’t use a StackLayout to host a single child Don’t use a Grid when a StackLayout would do Don’t use multiple StackLayout when a Grid would do ” Jason Smith at Evolve 2016
  • 49. AbsoluteLayout permette di posizionare e dimensionare controlli figlio in maniera assoluta utilizzando valori statici o proporzionali  Ideale se il Layout è facilmente descrivibile e indipendente dalla posizione di altre view  Massimo delle Performance  Poco Leggibile
  • 50. L’invalidazione di una delle View figlie provoca l’invalidazione a catena del Visual Tree fino ad AbsoluteLayout AbsoluteLayout permette di posizionare e dimensionare controlli figlio in maniera assoluta utilizzando valori statici o proporzionali <AbsoluteLayout> <Label Text="Hello Codemotion!" AbsoluteLayout.LayoutBounds=".02,.01" AbsoluteLayout.LayoutFlags="PositionProportional"/> <Label Text="Hello Codemotion!" AbsoluteLayout.LayoutBounds=".02,.05" AbsoluteLayout.LayoutFlags="PositionProportional"/> </AbsoluteLayout>
  • 51. Poiché lo spazio messo a disposizione degli elementi figlio è fissato staticamente, AbsoluteLayout ignora notifiche di invalidazione dai suoi figli AbsoluteLayout permette di posizionare e dimensionare controlli figlio in maniera assoluta utilizzando valori statici o proporzionali <AbsoluteLayout> <Label Text="Hello Codemotion!" AbsoluteLayout.LayoutBounds="10,10,200,100" /> <Label Text="Hello Codemotion!" AbsoluteLayout.LayoutBounds="10,30,200,100" /> </AbsoluteLayout>
  • 52.  Ideale se la dimensione o la posizione dei controlli del Layout è strettamente correlata  Peggiori Performance RelativeLayout permette di posizionare e dimensionare controlli figlio relativamente alla View contenitore o ad altre view del layout
  • 53. L’invalidazione di una delle View figlie provoca l’invalidazione del Visual Tree fino a RelativeLayout <RelativeLayout> <Label x:Name="Label1" Text="Hello Codemotion!" /> <Label Text="Hello Codemotion!" RelativeLayout.YConstraint= "{ConstraintExpression Type=RelativeToView, Property=Y, ElementName=Label1, Constant=20}" /> </RelativeLayout> RelativeLayout permette di posizionare e dimensionare controlli figlio relativamente alla View contenitore o ad altre view del layout
  • 54. ScrollView aggiunge la funzionalità di scrolling alla sua subview  Non innestare più ScrollView  Comportamenti poco intuitivi  Non innestare ListView  Rompe la virtualizzazione
  • 55. Demo GitHub Repo: bit.ly/2nVm2Ei N.B. Repo strutturata in submodule 1. Clonare la repo principale (fork di Xamarin.Forms): 2. Checkout sul branch layout: 3. Clonare la subrepo: 4. Avviare il progetto AppDemo4 dalla repo principale bit.ly/2nzxf1B bit.ly/2ndfZhE bit.ly/2nzypdt
  • 56.
  • 57. Il Binding è una funzionalità integrata nel framework Xamarin.Forms  Consente di creare associazioni loosely-coupled tra una proprietà Sorgente e una proprietà Target  Utilizzato assieme al pattern MVVM, permette di slegare Modello e View frapponendo uno strato di ViewModel Source Qualsiasi Object Target BindableObject BindablePropertyProprietà Pubblica Binding TwoWay OneWayToSource OneWay
  • 58. Binding 1 Scatenata notifica PropertyChange 2 Il Binding legge il valore della nuova proprietà 3 Il Binding aggiorna la proprietà Target p.Name = "Jerry"; public abstract class BindableObject : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } //... }
  • 59. Golden Rule “Don’t bind things that can be set statically” Jason Smith at Evolve 2016 public abstract class BindableObject : INotifyPropertyChanged { //... void SetValueActual(BindableProperty property, BindablePropertyContext context, object value, bool currentlyApplying, SetValueFlags attributes, bool silent); void SetValueCore(BindableProperty property, object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes); }
  • 60.
  • 61. Rendere la UI responsive:  Non interrompere la catena async/await bloccando il Thread principale su un operazione I/O Bound  Non eseguire Task altamente computazionali sullo UI Thread Obiettivo: 60 fps ad ogni animazione e transizione!
  • 62. Rendere la UI responsive:  Utilizzare il pattern asincrono per restituire subito il controllo alla Message Pump (UI Thread) - eventualmente ConfigureAwait(false)  Schedulare CPU-Bound Task su Thread secondari (Background Thread) Obiettivo: 60 fps ad ogni animazione e transizione! Task.Run() Task.Factory.StartNew() UI Thread DownloadAsync ReadingfromURL GetString LoadData I/O
  • 63. È possibile trarre vantaggio dalla separazione tra Inflating e Rendering delegando l’esecuzione della prima fase ad un Thread secondario Task<StackLayout> InflateOnBackgroundThread() { return Task.Factory.StartNew(() => { var stackLayout = new StackLayout(); stackLayout.Children.Add(new Label { Text = "Hello Codemotion" }); return stackLayout; }); } public MainPage() { InflateOnBackgroundThread() //... }
  • 64. Nel caso l’Inflating venga eseguito in un Thread secondario:  Non è possibile da BT modificare il Visual Tree  Per farlo, occorre restituire il controllo al Thread chiamante, in questo caso lo UI Thread InvalidOperationException public MainPage() { var uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); InflateOnBackgroundThread() .ContinueWith( task => AddToVisualTree(task.Result), uiTaskScheduler); } Catturare il contesto di sincronizzazione corrente Eseguire l’unmarshalling e l’aggiunta al VT nello UI Thread
  • 66.
  • 67. Un punto debole di un’applicazione Xamarin.Forms è rappresentato dai suoi tempi di avvio Il principale responsabile è l’avvio del sistema di Rendering ~ 1s
  • 68. 0 500 1000 1500 2000 2500 3000 3500 Android Initialization Time (Avg) Xamarin.Native Xamarin.Forms  Time profiled from App Start to View Rendering  Average calculated on a population of size 20  HW: LG Nexus 5X with Android 7.1 Nougat ms
  • 69. 0 200 400 600 800 1000 1200 1400 Android OnCreate Time (Avg) Xamarin.Native Xamarin.Forms  Time profiled on MainActivity OnCreate()  Average calculated on a population of size 20  HW: LG Nexus 5X with Android 7.1 Nougat ms
  • 70. 0 1000 2000 3000 4000 5000 6000 7000 8000 9000 UWP Initialization Time (Avg) Xamarin.Native Xamarin.Forms  Time profiled from App Start to View Rendering  Average calculated on a population of size 20  HW: Lumia 640 LTE with Build 10.0.14393.0 ms
  • 71. 0 1000 2000 3000 4000 5000 6000 7000 UWP OnCreate Time (Avg) Xamarin.Native Xamarin.Forms  Time profiled on App OnLaunched()  Average calculated on a population of size 20  HW: Lumia 640 LTE with Build 10.0.14393.0 ms
  • 72. 0 500 1000 1500 2000 2500 3000 3500 4000 4500 5000 iOS Initialization Time (Avg) Xamarin.Native Xamarin.Forms  Time profiled from App Start to View Rendering  Average calculated on a population of size 20  HW: iPhone Simulator 7 Plus with iOS 10.2 ms
  • 73. 0 200 400 600 800 1000 1200 1400 iOS FinishedLaunching Time (Avg) Xamarin.Native Xamarin.Forms  Time profiled on AppDelegate FinishedLaunching()  Average calculated on a population of size 20  HW: iPhone Simulator 7 Plus with iOS 10.2 ms
  • 74. Per risolvere questo problema si può pensare di trarre vantaggio dei tempi di caricamento minori di Xamarin.Native 1. Si avvia l’app seguendo le modalità native e non si inizializza il sistema di rendering di Forms 2. Si utilizza una View nativa come prima Pagina 3. Si avvia l’engine di Xamarin.Forms in un secondo momento (e.g. tramite callback, timer, metodi asincroni…) 4. Si utilizzano da qui in poi le API di Forms - eventualmente solo quando servono (e.g. View semplici come Settings, Login, ecc.)
  • 75. Tutto molto bello ma ancora non supportato da Xamarin.Native Xamarin.Forms Feature Roadmap Ma…
  • 76. public class FormsActivity : FormsAppCompatActivity { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); var pageName = Intent.Extras.GetString("PageType"); var fullName = typeof(FormsApp).Namespace + ".Pages." + pageName; var pageType = typeof(FormsApp).Assembly.GetType(fullName); if (!IsFormsInitialized) { global::Xamarin.Forms.Forms.Init(this, bundle); IsFormsInitialized = true; } LoadApplication(new FormsApp(pageType)); } } Possiamo utilizzare le API attuali per caricare pagine Xamarin.Forms in progetti Xamarin.Native – per View e Layout bisogna però aspettare… var intent = new Intent(this, typeof(FormsActivity)); intent.PutExtra("PageType", "SettingsPage"); StartActivity(intent); public FormsApp(Type pageType) { MainPage = (Page)Activator. CreateInstance(pageType); } Dopodiché, si avvia normalmente l’Activity con le API di Xamarin.Android passando l’indicazione della pagina Forms nel Bundle Extra
  • 77. public class FormsWrapperPage : WindowsPage { private readonly FormsApp _formsApp; public FormsWrapperPage() { this.InitializeComponent(); LoadApplication(_formsApp = new FormsApp()); } protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); _formsApp.SetMainPage(e.Parameter as Type); } } Possiamo utilizzare le API attuali per caricare pagine Xamarin.Forms in progetti Xamarin.Native – per View e Layout bisogna però aspettare… Dopodiché, si utilizzano normalmente le API di Navigazione di UWP passando come parametro di navigazione il tipo della Pagina Forms di destinazione public SetMainPage(Type pageType) { MainPage = (Page)Activator. CreateInstance(pageType); } this.Frame.Navigate( typeof(FormsWrapperPage), typeof(SettingsPage));
  • 78. Possiamo utilizzare le API attuali per caricare pagine Xamarin.Forms in progetti Xamarin.Native – per View e Layout bisogna però aspettare… Nel caso di iOS la classe Xamarin.Forms.PageExtensions espone il metodo di estensione CreateViewController  Dopodichè, si può presentare il ViewController utilizzando le API di Xamarin.iOS public static Page GetPage<T>() where T : Page { return Activator.CreateInstance<T>(); } var settingsViewControler = FormsApp.GetPage<SettingsPage>().CreateViewController(); await this.PresentViewControllerAsync(settingsViewControler, true);