Sunday 15 November 2015

Using Xamarin.Forms List caching and Lazy loading of infinite list

Today I will walk through a simple implementation lazy loading of a list view with xamarin.forms.

A walk through application will give a clear idea to the beginners. For more experienced people use  ItemAppearing property.

1) How to use MVVM with xamarin.forms.
2) How to use sqlite caching in your application.
3) Lazy loading with xamarin.forms list view.

You can browse through the code https://github.com/shribits/ListViewPagingAndCaching

Step 1:

1) Create a xamarin.forms project with PCL.
2) Add in xamarin.forms package from nuget.


Step 2:

1) As we are using mvvm in our application, we will segregate the model, view model and views. We will also have a service layer which will fetch the data from the backend(like a rest service).

Step 3:

Deep dive into the implementation:

Model , ViewModel and View:

ExampleModel contains the same data forma as the web service layer. This model type will be used to deserialise the response from the rest call.

public class Example
{
    public IList<Result> results { get; set; }
    public int count { get; set; }

}  

ExampleViewModel gets the data from the service layer:

public async Task UpdateViewModel()
{
   IsLoading = true;
   ResultItems =  await exampleService.GetItems ();
   Debug.WriteLine(ResultItems[0].channel);
   foreach (var item in ResultItems) {
        CollectionItems.Add (item);
   }
   IsLoading = false;
}




Example service layer gets the data from the web service as below and write to the sqlite database. If the there is a network outage then it will just read from the database only.

public async Task<List<Result>> GetItems()
{
    exampleItems = new List<Result> ();
    try{
        await GetActivityItems ();
        await cacheService.AddOrUpdateExampleItem (exampleItems);
     }catch
     {
              
     }
     return cacheService.GetExampleItem ();
}

private async Task GetActivityItems()
{
    try{
       var client = new RestClient ("http://www.whatsbeef.net");
       var request = new RestRequest ("/wabz/guide.php?start="+AppConfig.AppElementCounter);
       IRestResponse response = await client.Execute (request);
       RestSharp.Portable.Deserializers.JsonDeserializer deserial = new RestSharp.Portable.Deserializers.JsonDeserializer ();
       var deserializedResponse= deserial.Deserialize<Example> (response);
       Items= deserializedResponse.results ;
       foreach (var item in Items) {
            exampleItems.Add (item);
          }
       AppConfig.AppElementCounter+=10;
       }
       catch(Exception ex){
          #if DEBUG
          Debug.WriteLine (ex);
          #endif
       }
}
  


For caching:
Two dependency service has been written, first one is to get the device specific path and the second one is for platform specific sqlite connection.



public static SQLiteConnection CreateDB()
{
   var localDB =  DependencyService.Get<IDocumentPathService>    ().CreateDocumentPath("Shri.db3");
   return new SQLiteConnection (DependencyService.Get<IDataStore>().SqlitePlatform,localDB),true);
}


Finally we need to finish the implementation of on demand loading:


list.ItemAppearing += (sender, e) =>
{
    MessagingCenter.Send<ExamplePage,Result>(this,"LoadItems",e.Item as Result);
};
  


So xamarin.forms listview has a property called ItemAppearing. This call results in returning the item appearing on the screen. You can match if the last item has already appeared on the screen then load more items.

In my next article I am going to share a few animation implementations.

Thanks
Shri