Content

7/05/2011

XING-App for Windows Phone 7 Architecture



In this article I will write about our architecture for the XING-App for WP7 developed by Zühlke.
Most existing apps need connectivity to run properly. You start your app and the first you see is a "loading"-icon and in many cases working without any connection is impossible.
The default state of the XING-App is offline. First we load the local cache and display the content. The user decides when to synchronize with the server. Especially for XING it is quite useful to be able to have a quick look in your XING-Network at all times, even if you're offline. Also you will have no roaming problems. When you run the app for the first time or have no data locally cached then the app initially synchronizes with the server and saves the data in the local cache.

The application is developed using the MVVM-Pattern shown in the picture below.


Services contain web service calls. All method calls contain a success callback and an error callback. Service methods are only called from background threads. The web service responses are parsed and translated into objects. 

sample service call
  1.     IsSyncing = true;
  2.     contactService.GetContacts(
  3.         userScope.UserId, updatedContacts =>
  4.         {
  5.             this.userScope.Contacts.Data = updatedContacts;
  6.             userScope.Contacts.LastUpdated = DateTime.UtcNow;
  7.             IsSyncing = false;
  8.             HandleSuccessHandlers();
  9.             Status = StoreStatus.Online;
  10.         },
  11.         Dispatch.Action<Exception>(ex =>
  12.         {
  13.             RemoveSuccessHandle(callback);
  14.             IsSyncing = false;
  15.             HandleError(ex);
  16.         }));


Stores observe the access to a web service and manage the cache.  
The store decides if the data will come from the cache or from the web service. After the application starts the data is loaded from isolated storage. When the application is shut down,  data is saved into isolated storage. Each store has a LocalStorage class for loading and saving. These classes load the content from their own file and save the data using a BinarySerializer. The store contains the information when the data was last synchronized. And each store has its own validation time for the cache.
A store has an Offline-, Online or Broken-State.

 
The store has no UI code like INotifyPropertyChanged or ICollectionChanged. Views receive the requested data from the success callback. Each store method is called with a success callback, most likely from the ViewModel, PropertyChanged event is called to inform the UI. If an error occurs the StatusChanged event from the Store is called. In our XING-App each ViewModel implements the StatusProvider interface to handle the status changed in the UI. Therefore each page has a statusbar to display the current status. For example if there is currently no connectivity the offline status is displayed along with the time when the data was last synchronized. The color of the status depends on its state.


sample store call
  1.     IsSyncing = true;
  2.     visitStore.GetMoreVisits(loadedVisits =>
  3.     {
  4.         AppendVisits(loadedVisits);
  5.         RaisePropertyChanged("HasMoreData");
  6.         IsSyncing = false;
  7.     });

Store methods and events are only called from the UI-Thread.
The stores do not know one another.
If several methods are called in a row then the success callbacks are queued. The first web request is called and no further success callback are called during the synchronization. After the web response the upcoming success callbacks are called.
In order to ensure a better response and a better feedback of our data for the UI, the success callback is first called with the data from the local cache. The success callback is called again after the web request has sent its response.  


The ViewModel prepares the data for the UI. If a store method is called to receive data, we will actually send a web request.
All methods in the ViewModel are called from the UI-Thread. ViewModels do not know one another. You can use a message infrastructure to inform other ViewModels and your business logic is done.

No comments:

Post a Comment