MvvmCross: Accessing models by reference from everywhere

 

The MvvmCross screen navigation system is very powerful and solves in a very elegant way a lot of common situations. However, there are some cases where it might be worth to move more complex data between ViewModels than the framework allows us to.

Most mobile apps provide a list where users can tap on each item to see its details. The most common way to solve this kind of scenarios with MvvmCross is to pass the id of the entity on ShowViewModel method and then recover the entity from a SQLite database on Init/Start method. However, when the details screen becomes complex (like splitted on different tabs/screens with possible edit mode) or when it is used across many places, keeping the item updated everywhere on your app can be a challenge that ends up sometimes with dirty solutions (like spamming messages using the MvxMessenger plugin).

Wouldn’t it be wonderful if you could have the same entity instance in all places and just forget about updating it? The solution is pretty easy and is provided by the usage of the well known Singleton pattern. It requires you to add one interface and its implementation to your app:

As you can see, the concept is quite simple. There is just one property: the wrapped item.

The next step is to register the object wrapper inside MvvmCross IoC system as a singleton, inside your custom App.cs class:

Ok, so now everything is set up. To use the singleton object wrapper you now have to inject it using the MvvmCross DI system:

As you can see, there is no need to pass any parameter to ShowViewModel method.

Now the singleton object wrapper must be injected into DetailViewModel as well (and as you can imagine, in every ViewModel that uses the object instance):

At this point nothing stops you from creating a public property inside each “consumer” ViewModel, which can be bound to visual elements on each platform:

And here comes the magic! Since it is the same instance object, any change you do to the object will impact on every ViewModel!

You can have many singleton object wrappers for different entity types and happily have a single reference of each one in your entire app.

 


 

A word of disclaimer

Although the previous solution is super useful when dealing with apps that focus on CRUD operations from a single or a few entity types, keep in mind that using the singleton pattern this way means having objects whose memory allocations will be kept alive the most time your app runs. Therefore you should consider cost-benefits fist.

One way to drop the allocations number and size is to set the UniversalObject to null after you have finished using it (for instance, once the user goes back to the list screen, the universal item is no longer needed). As a result the singleton object will be kept in memory, but all references to the UniversalObject will be happily collected by the GC.

 

Nicolas Milcoff – Federico Maccaroni

Leave a Reply

Your email address will not be published. Required fields are marked *