TRUNGTQ

Think Big, Act Small, Fail Fast and Learn Rapidly

NAVIGATION - SEARCH

Xamarin Diaries – Offline by default (Part II)

Xamarin Diaries

Hi All!

In this new chapter we’ll continue talking about offline functionality in Xamarin.Forms apps. This time I want to cover the possibilities we have to store our data locally.

If you remember from the previous post  – Xamarin Diaries – Offline by default (Part I) -, when we retrieve data from backend (typically in JSON format) the first thing we do is to synchronize our local data. Next time we run the same query this data can be directly retrieve from local storage (specially if we fall into offline conditions).

For this local storage we can choose between two different possibilities:

  • SQLite
  • Text JSON files

Let’s take a deeper look into the two options:

SQLite

This is the standard solution and it’s probably the solution I would go in most cases. Basically you will need to add some of the SQLite plugins to start. If we take a look to nuget there are two main plugins according to number of downloads:

The second options is no longer maintained and it is in fact a fork of the first one so the first option is my recommendation.

As an important point, sqlite-net-pcl last updates already include references to sqlitepclraw green to avoid problems with restrictions added with Android N. If you go with the second option you will have to add them manually.

Pros

Performance: SQLite performance is better than reading and overwriting files. For little applications it is probably not a problem, but when applications grow it is better to have indexes and transactions on your side.

Security: Although sqlite databases are just a db3 file stored inside Personal folder (so they are more or less the same than json files), they allow developers to add security layers. For example you have raw-cipher https://www.nuget.org/packages/SQLitePCLRaw.bundle_sqlcipher/ for encryption

Standardization: standardized solutions are always better when it comes to business. Maintainability and scalability are linked to standardization.

Cons

Ease of implementation: you will find that multi level hierarchies in the model of your application are not well supported in SQLite, and so do one-to-many and many-to-many relationships. You can use the ORM layer included in sqlite-net or add some other plugins, but in my experience, I prefer to do it myself by applying manual conversions. For example, something like:

Can be converted to:

public class IncidentTypeItem
{
public string Id { get; set; }
public string DescriptionEs { get; set; }
public string DescriptionEn { get; set; }
public string DescriptionPt { get; set; }
public string DescriptionCa { get; set; }
}

 

With the following converter

public static class IncidentTypeToIncidentTypeItem
{
public static IncidentTypeItem Convert(IncidentType incident)
{
var item = new IncidentTypeItem
{
Id = incident.Id,
DescriptionEs = incident.Description.Spanish,
DescriptionEn = incident.Description.English,
DescriptionPt = incident.Description.Portuguese,
DescriptionCa = incident.Description.Catalan
};
return item;
}
public static IncidentType Unconvert(IncidentTypeItem item)
{
var incident = new IncidentType
{
Id = item.Id,
Description = new Description
{
Spanish = item.DescriptionEs,
English = item.DescriptionEn,
Portuguese = item.DescriptionPt,
Catalan = item.DescriptionCa
}
};
return incident;
}
}

 

JSON Files

This option could sound as a no so beautiful solution but in some cases I found it very useful in situations you just need something quick that could work as cache.

For this solution you will need a connector so that you can manipulate files natively in Android and iOS from PCL Project. I have leave it in github if case you want to take a look to it: https://github.com/dhompanera/XamarinDiaries/tree/master/Offline

When working with JSON files as cache you will basically do something like this:

Save items to local storage:

var itemsAsJson = JsonConvert.SerializeObject(Items, Formatting.Indented);
DependencyService.Get<IFiles>().SaveText(string.Format("items_{0}.json", AuthManager.Instance.User.Id), itemsAsJson);

 

Retrieve items from local storage:

var jsonText = DependencyService.Get<IFiles>().LoadText(string.Format(“items_{0}.json", AuthManager.Instance.User.Id));
var jsonResponse = JsonConvert.DeserializeObject<List<Item>>(jsonText);
if (jsonResponse != null && jsonResponse.Count > 0)
{
Items = jsonResponse;
}

 

Special mention to Newtonsoft.Json (https://www.newtonsoft.com/json) as library to manipulate json objects.

Pros

Ease of implementation: There is no need to create conversor or anything, you just read from file and apply same json parse than in for your model.

Performance: For small applications is it just fast enough. I wouldn’t use it if the app grows.

Cons

Security:  No security for files, they are plain text stored in Personal folder. You could apply some cipher to encrypt the content of the files, but I just find it too difficult for a solution only thought for simple uses.

Performance: It can be compromised if the app grows.

Summary

As a continuation from the first post, we have learnt different possibilities we have to provide our applications with offline functionality. Either with SQLite or with JSON Files, we can get more robust apps that work in low connectivity situations.

LINK: https://solidgeargroup.com/xamarin-diaries-offline-by-default-part-ii

Xamarin Diaries – Offline by default

Xamarin Diaries

Hi All!

In this new chapter of Xamarin Diaries will dive into one of the top three questions we got in Xamarin forums: How can I take advantage from offline capabilities with Xamarin Forms?

When we develop a mobile application there are some things we can do to boost up the UX. The one I like the most is offline capabilities. If you think about it, although mobile network are faster than ever and coverage is getting bigger day by day, it is still very common to get into a situation with poor or null connectivity (subway, a trip to the mountains, inside an industrial area…). In that situation we find two kind of applications:

  • The ones that get stuck on loading spinner until a timeout fires and then turn blank or block us from using the app.
  • The ones that manage cache data and connectivity and show you latest information loaded and even allow you to do some functions with it.

In this entry we will give you some tips on how to build applications in the second category.

Architecture

If you have read or watched any of our posts or videos you already know we build our Xamarin apps using MVVM pattern for the UI. This allows us to decouple representation from behaviour.

Also we use a classic MVC to decouple view (MVVM) from services (we’ll cover ti in future posts).

MVVM

MVVM

Xamarin.Forms helps us to reach our goal by providing us with some good resources:

  • Data bindings
  • Commands

Data binding is the way we have to link an interface item (label) with some viewmodel property:

  1. <Label Text=”{BindingFruit.Name}”/>

Command allows to execute some action in the viewmodel from the view:

  1. <Button Text=”Send” Command=”{BindingSendCommand}”/>

We will take advantage from both of them to get offline functionality. How? Keep reading.

Asynchronous working

Take a look to the following picture:

MVVM implementation

In ViewModel you can see we define two command methods in the viewmodel: One to load items stored in our local repository (typically a sqlite database or json files) and other to refresh those items with remote information (from an api rest for example).

We call these two commands from two differents methods in view’s code behind.

  • Local load is launched from constructor, what of course happens the first thing in page’s lifecycle.
  • Remote refresh is called from OnAppearing method. OnAppearing is fired when all the elements have been rendered. This in practice gives local load some time to complete.

Both local and remote loads inject retrieved items in the same items collection.

ObservableCollection vs List

This item collection has to implement observable interface to be able to update items in the view when they are refreshed by invoking PropertyChanged event (if you don’t know what i am talking about you need to take a deepful look to MVVM Pattern, specially to INotifyPropertyChanged). Usually we use ObservableCollection:
  • The main disadvantage of using it is it needs an adhoc update process. The reason for that is it binds every individual element with its listview representation and you cannot just clear all the thing up, assign it again and hope everything will work. You need to loop through all the items in the collection, find the differences and call PropertyChange on each of them.
  • The main advantage of doing what for me is the best solution is that the User will see that a first list is loaded and that once the remote data is retrieved, the elements are updated in a fluid way, without flickering.

If you want to do it quicker or simply it is enough for your app, you can just use a List instead of an ObservableCollection. In a List, we can call Clear, assign the whole list again and call Propertychange for the whole list. We will see a little flickering in the UI, but from my experience, most of the times it is good enough.

So the process is like this:

  • On page’s constructor we call loadlocalitems. It takes few time as it is just a local access to the repository and populates items list.
  • This items list is usually represented in the UI with a ListView. Local items get represented in the UI.
  • On page’s OnAppearing method we call refreshremoteitems. It could be a long asynchronous call to an api rest. Nevermind, as you are using async funtions, UI won’t get stuck.
  • When it finishes it updates items list and updated items get represented in the UI.

Here is where we introduce Connectivity check.

Offline working

For this purpose we will use the following plugin: https://github.com/jamesmontemagno/ConnectivityPlugin from James Montemagno

It provides a simple way to check if there is connectivity:

  1. if (!CrossConnectivity.Current.IsConnected)
  2. {
  3. return;
  4. }

We integrate it in the refresh remote load to check at the beginning if there is connectivity. If there is not, you just need to cancel it. As the local data has already been prompted to the user, we don’t need to do any further operation.

It is recommended, anyway, to prompt the user somehow when there is no connection. We can use IsConnected status to show the user a tag or a red color. Also we can use connectivity event provided with connectivity plugin to alert the user when a change in connection is fired.

Summary

We have learnt how to build robust apps by providing them with and offline ready architecture. We have also learnt how to take advantage of the resources Xamarin Forms give us to make that architecture possible.

LINK: https://solidgeargroup.com/xamarin-diaries-offline-by-default