One of the most important features of modern mobile phones is the ability to access web content. After a short example on downloading information from a remote server, we will deal with a combination of sending and receiving data.
Web requests always cause a certain delay (at least 100 milliseconds, but usually much longer). Therefore, we take the opportunity to sneak into asynchronous background threading. This way the app will build the UI immediately and remain responsive to user interaction, while the content data is downloaded in the background.
10.1 Asynchronous web requests
To demonstrate asynchronous web requests with Xamarin.Forms we implement a web-based clock app. It will allow the user to ask a web server for the current time. While loading the JSON response, the UI will display a “Loading…” string and remain responsive to user input. For example, pressing the back button will allow the user to leave the page before finishing the download.
Of course, asking for the current time is just a very simple example and usually doesn’t take very long. But still: The delay is noticeable and a responsive high-quality app should not perform such tasks on the UI thread. For more complex scenarios the importance of separating UI and background tasks is even larger.
We start with a MainPage containing a button that opens a new TimePage.
MainPage = new NavigationPage(new ContentPage {
Content = new Button {
Text = "What time is it?",
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand,
Command = new Command(() => MainPage.Navigation.PushAsync(new TimePage())),
},
});
The class TimePage is derived from ContentPage and is described in the following. It only contains a single visual element, namely a timeLabel centered on the page. Initially it shows the text “Loading…”.
readonly Label timeLabel = new Label {
Text = "Loading...",
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand,
};
The constructor of our TimePage only assigns the timeLabel to the page content.
public TimePage()
{
Content = timeLabel;
}
Now we deal with downloading the current time from the web. Therefore, we override the OnAppearingmethod of TimePage: It should request the time asynchronously and assign the result to the label text.
protected override async void OnAppearing()
{
base.OnAppearing();
timeLabel.Text = await RequestTimeAsync();
}
Note that the execution of RequestTimeAsync is awaited using the await keyword. Because this is not allowed within the constructor, we chose to override the OnAppearing method. When overriding a method, you can decide whether to make it a synchronous or asynchronous method by adding the async keyword.
The RequestTimeAsync method will perform the actual web request. As indicated by the common suffix Async it is an asynchronous method. It creates a new HttpClient and requests a string from http://date.jsontest.com/, which looks as follows:
{
"time": "09:37:49 AM",
"milliseconds_since_epoch": 1417685869463,
"date": "12-04-2014"
}
The method JObject.Parse allows to convert the string into a json object, which can be used like a dictionary to access fields like "time". Note that you need to add the Json.NET packages for iOS and Android (listed as “Newtonsoft.Json” in the project’s “Packages” folder).
static async Task<string> RequestTimeAsync()
{
using (var client = new HttpClient()) {
var jsonString = await client.GetStringAsync("http://date.jsontest.com/");
var jsonObject = JObject.Parse(jsonString);
return jsonObject["time"].Value<string>();
}
}