Conquer the network!
Roy Cornelissen
Xpirit
@roycornelissen
#TECHDAYSNL #XAMARIN
Slide 2
Slide 2 text
No content
Slide 3
Slide 3 text
Agenda
Slide 4
Slide 4 text
No content
Slide 5
Slide 5 text
8 fallacies of
1. The network is reliable.
2. Latency is zero.
3. Bandwidth is infinite.
4. The network is secure.
5. Topology doesn't change.
6. There is one administrator.
7. Transport cost is zero.
8. The network is homogeneous.
Deutsch - 1994
Gosling - 1997
distributed computing
Slide 6
Slide 6 text
Threads
Don’t occupy the UI Thread with
network I/O or CPU bound work
like serialization
Slide 7
Slide 7 text
Common pitfalls
with async/await
Slide 8
Slide 8 text
No content
Slide 9
Slide 9 text
Calling .Run(), .Wait() or .Result on a Task
async Task MyMethod(int parameter) { }
MyMethod(10).Run();
This will execute the task on the same thread, blocking the UI thread
var result = await MyMethod(10);
// async all the way!
Pitfall
Slide 10
Slide 10 text
Unnecessarily returning to the UI Thread
await DoLotsOfNetworkCalls();
public async Task DoLotsOfNetworkCalls() {
await httpClient.GetAsync(“…”);
// do some calculations or de-serialization
await httpClient.GetAsync(“…”);
}
After each await, execution will continue on the original
thread, causing interruptions and even possibly deadlocks.
await httpClient.GetAsync(“…”).ConfigureAwait(false);
// use ConfigureAwait(false) in your library code
Pitfall
Slide 11
Slide 11 text
Creating async void methods
async void MyMethod(int parameter) { }
Awaiting this method will fail
This is a Fire & Forget call, you cannot do any proper error handling
async Task MyMethod(int parameter) { }
async void OnClick(object sender, EventArgs e)
{ } // Exception: async event handlers!
Pitfall
Slide 12
Slide 12 text
Not awaiting async UI methods
Navigation.PushAsync(new DetailView());
await Navigation.PushAsync(new DetailView());
Can cause deadlocks, freezing UI or white
screens
Pitfall
Slide 13
Slide 13 text
Demo App
RESTful api
Repo: https://www.github.com/xpiritbv/ConquerTheNetwork
API: http://vslivesampleservice.azurewebsites.net/api/cities
Slide 14
Slide 14 text
Goals
• Easily access RESTful API’s
• Fast response to the user
• Work offline
• Deal with errors
Slide 15
Slide 15 text
Standing on the
shoulders of giants
Slide 16
Slide 16 text
Easily access
Restful
Api’s
Slide 17
Slide 17 text
Easily access Restful Api’s
Refit
• Install-Package Refit
Turns a RESTful API into a typesafe interface
public interface IGitHubApi {
[Get("/users/{user}")]
Task GetUser(string user);
}
Component by: Paul Betts, http://github.com/paulcbetts/Refit
Slide 18
Slide 18 text
Faster response
to the user
Slide 19
Slide 19 text
Faster response
Akavache
• Install-Package Akavache
On device cache based on SQLite local
database.
You must include SQLite in the Windows app as well.
Component by: Paul Betts, http://github.com/paulcbetts/Akavache
Slide 20
Slide 20 text
SQLITE-NET
A lightweight ORM suitable for mobile application development
Slide 21
Slide 21 text
SQLite.org
SQLite
• Cross-platform format; stored as a single file
• 32 or 64 bit; big or little endian
• Most of SQL92
• Missing some OUTER joins
• Only supports TABLE RENAME
& ADDCOLUMN
• Views are read only
Slide 22
Slide 22 text
Configuration
– SQLite just needs to know where the database file is
stored.
– The location must be writable!
• If you bundle a database file in your app, copy it
out first!
• Different platforms “care” about different things
• Android: choose internal or external storage
• iOS: choose Documents, Library or other
Slide 23
Slide 23 text
public class Session
{
[PrimaryKey, AutoIncrement, Column("_id")]
public int Id { get; set; }
public string SpeakerName { get; set; }
public string Title { get; set; }
public string Abstract { get; set; }
public string Location { get; set; }
public DateTime Begins { get; set; }
public DateTime Ends { get; set; }
}
Model Classes
Slide 24
Slide 24 text
db.CreateTable ();
db.Insert (session); // after creating the session object
Executing Commands
Slide 25
Slide 25 text
• The SQLite library is not thread safe
• Don’t use the same Connection across threads
• Always use lock () statements
lock (locker){
// Do your query or insert
here
}
Threading
Slide 26
Slide 26 text
Core OS layer
OS API layer
Mono
stack
Application layer
Faster
network requests
Slide 27
Slide 27 text
Core OS layer
OS API layer
Mono
stack
Application layer
ModernHttpClient
Faster
network requests
Slide 28
Slide 28 text
ModernHttpClient
• Install-Package ModernHttpClient
Leverages the native OS network stack by swapping in a
NativeMessageHandler:
• NSURLSession on iOS
• OkHttp on Android
Beware: exceptions are not the same as with plain HttpClient (e.g. Java web exceptions)
Beware: iOS App Transport Security (use TLS2.0 edit info.plist)
Component by: Paul Betts, http://github.com/paulcbetts/ModernHttpClient
Faster
network requests
Slide 29
Slide 29 text
Choose network stack in csproj options
Faster
network requests (alternative)
Slide 30
Slide 30 text
Use AndroidClientHandler
Uses native java.net.URLConnection
Faster
network requests (alternative)
var client = new HttpClient (
new Xamarin.Android.Net.AndroidClientHandler ());
Slide 31
Slide 31 text
Sometimes you
want to work
offline…
Slide 32
Slide 32 text
Work Offline
No network: why bother?
Prevent nasty waits and
errors
Slide 33
Slide 33 text
Connectivity Plugin
• Install-Package Xam.Plugin.Connectivity
Provides a cross platform way to check the
connectivity of the device before trying to
issue a network request.
Component by: James Montemagno, https://github.com/jamesmontemagno/Xamarin.Plugins
Work Offline
Slide 34
Slide 34 text
No content
Slide 35
Slide 35 text
What could go wrong?
Slide 36
Slide 36 text
What do you do?
Retry
• How many times?
• At what interval?
• What if the server is already busy?
Circuit breaker
• Elegant pattern for failing fast after
network errors
Slide 37
Slide 37 text
Polly
• Install-Package Polly
Implement error handling policies by
declaratively specifying retry, circuit breaker
etc. Polly will do the heavy lifting.
Polly by: Michael Wolfenden, https://github.com/michael-wolfenden/
Handle errors
Slide 38
Slide 38 text
Fody.AsyncErrorHandler
• Install-Package Fody.AsyncErrorHandler
Globally handle errors that happen in async
(background) code. Useful for catching
otherwise hidden errors. Uses a Fody IL weaver.
Fody.AsyncErrorHandler by: Simon Cropp, https://github.com/Fody/AsyncErrorHandler
Handle errors
Slide 39
Slide 39 text
Easily access RESTful API’s: Refit
Fast response to user: Caching, ModernHttpClient,
async
Work offline: Akavache, Connectivity Plugin
Deal with errors: Polly, Fody.AsyncErrorHandler
Goals